jhass changed the topic of #crystal-lang to: The Crystal programming language | https://crystal-lang.org | Crystal 0.35.1 | Fund Crystal's development: https://crystal-lang.org/sponsors | GH: https://github.com/crystal-lang/crystal | Docs: https://crystal-lang.org/docs | Gitter: https://gitter.im/crystal-lang/crystal
<FromGitter> <domgetter> So if I don't need inheritance, modules, or custom methods, then struct vs nametuple doesn't matter?
<FromGitter> <Blacksmoke16> named tuples are still inferior
<FromGitter> <Blacksmoke16> they're just not meant for this kind of use case
<FromGitter> <domgetter> the inferiority of nametuples has been implied and explicitly claimed multiple times in this conversation
<oprypin> yes
<oprypin> @jrei:matrix.org has requested some examples of how you're passing them around
<oprypin> i'm personally even having trouble imagining that being done realistically
<FromGitter> <Blacksmoke16> wouldnt be terrible, but :shrug: `Array(NamedTuple(name: String, area: Int32))`
<FromGitter> <Blacksmoke16> or alias it...but at that point its just a struct with extra steps
<FromGitter> <domgetter> What's so inferior about them?
<FromGitter> <jrei:matrix.org> That's hard to debate if x is better than y if there are no context.
<FromGitter> <domgetter> It was suggested devoid of context
<oprypin> domgetter, thats why we're asking for an example, to show also an example what's inferior
<FromGitter> <jrei:matrix.org> If you can just send a little snippet of what you're trying to do, we'll help
<FromGitter> <jrei:matrix.org> on carc.in
<FromGitter> <domgetter> I was trying to see if a block parameter list could destructure namedtuples. But that question was answered a while back.
<FromGitter> <Blacksmoke16> what i mentioned earlier, lot more verbosity on typing, just a lot harder to work with in general. Granted if you're not really doing anything at all named tuples may appear as a simple thing
<FromGitter> <jrei:matrix.org> Perhaps you're right on your very particular use case
<oprypin> domgetter, part of the answer is, your desire to destructure comes from the fact how inconvenient it is to access members from namedtuple
<FromGitter> <domgetter> can structs be destructured?
<oprypin> generally no. if u really wanted u could implement that
<FromGitter> <Blacksmoke16> `shapes.each do {|s| "Shape #{s.name} has an area of #{s.area}" }`
<FromGitter> <Blacksmoke16> can just use methods
deavmi has quit [Ping timeout: 272 seconds]
<FromGitter> <domgetter> I'd want to destructure either thing, so this has nothing to do with convenience of access of namedtuples specifically
<FromGitter> <Blacksmoke16> mmk
<FromGitter> <Blacksmoke16> then the answer is no you cant do that
<FromGitter> <Blacksmoke16> but isnt the point of destructuring to allow accessing certain values on an obj?
<straight-shoota> you can deconstruct a named tuple for named arguments
<FromGitter> <jrei:matrix.org> We can't help you more because we don't know what result you want to achieve.
<FromGitter> <Blacksmoke16> if so i dont see how `shapes.each do {|(name, area)| "Shape #{name} has an area of #{area}" }` is better than what i pasted earlier
<straight-shoota> and that's really the only use case for named tuples
<FromGitter> <domgetter> The kind of result I'd want to achieve is the ability to write `shapes.each do {|name:, area:| puts name; puts area*2}` and I now know that Crystal doesn't have anything like that
<FromGitter> <Blacksmoke16> 🤔 `shapes.each do |s| { puts s.name, s.area * 2 }` tada?
<FromGitter> <Blacksmoke16> but yes, crystal doesnt have that, so will have to use something else
<FromGitter> <Blacksmoke16> using a named tuple would be like `shapes.each { |s| puts s[:name], s[:area] * 2 }`
<FromGitter> <domgetter> I was then very confused that I was being told to use structs instead, and then when I asked why, it was said that context was needed to know when structs are good, even though the suggestion was given without context. So you can understand my confusion.
<FromGitter> <Blacksmoke16> context would help the end goal of your problem, dont really need context to say someone should use a strict over a named tuples when 99% of the time structs are better
<FromGitter> <domgetter> I really personally don't mind typing shape["name"] instead of shape.name
<FromGitter> <Blacksmoke16> mmk, you do you )
<FromGitter> <Blacksmoke16> going to be a nightmare if you ever want to refactor that tho
<FromGitter> <domgetter> but what makes structs better for passing some data around?
<FromGitter> <Blacksmoke16> more flexible with the same perf
<oprypin> it's an actual **type**, u know?
<FromGitter> <Blacksmoke16> i.e. you could do like `abstract struct Shape`, `struct Circle < Shape` etc
<FromGitter> <domgetter> my namedtuples are an actual type too
<FromGitter> <Blacksmoke16> technically but not really
<oprypin> a city also has a name and an area
<FromGitter> <Blacksmoke16> the type is describing the data, but that doesnt really mean its a specific type
<oprypin> doesnt make it a shape
<oprypin> oh wait, it does, under your definition
<FromGitter> <jrei:matrix.org> please paste a snippet on https://carc.in/
<FromGitter> <Blacksmoke16> `{name: "circle", area: 10, type: "shape"}` :trollface:
<FromGitter> <jrei:matrix.org> so we can stop talking on theories, and talk about practical code
<FromGitter> <domgetter> I don't understand how this is "my" definition. Crystal is the one assigning types to things
<FromGitter> <Blacksmoke16> but you're the one using them in this way
<FromGitter> <Blacksmoke16> this issue isnt specific to you
<FromGitter> <Blacksmoke16> but it is your code suggesting that just having `{name: "circle", area: 10}` represents a `Shape` when you have no way to actually know that from a lang perspective
<oprypin> domgetter, you could also be using `["circle", 10]` but can you blame crystal for the choice of type?
<FromGitter> <Blacksmoke16> versus being able to do like `obj.is_a? Shape`
<FromGitter> <domgetter> Looks like an `Array(String | Int32)` to me
<oprypin> yea
<FromGitter> <Blacksmoke16> right, but when you have an `Array(Array(String | Int32))` called `shapes`
<oprypin> now, does `alias Shape = Array(String | Int32)` look wrong to you?
<FromGitter> <jrei:matrix.org> or Tuple
<oprypin> well to us, aliasing it as a namedtuple looks almost as wrong
<FromGitter> <domgetter> who said I was aliasing anything?
<oprypin> ok ima head out
<FromGitter> <Blacksmoke16> > because that's what the type of the literal is
<FromGitter> <jrei:matrix.org> we don't know anything, please provide code, that's the issue
<FromGitter> <Blacksmoke16> we kinda been assuming your code thinks that your named tuples are representing shapes, maybe thats not accurate?
<FromGitter> <domgetter> I didn't provide code before, and oprypin was happy to suggest that I should use structs instead of whatever I was doing. So forgive me for thinking that we could resolve this through context-less discussion
<FromGitter> <Blacksmoke16> just because you mentioned named tuples and the obj was called `shapes` so we kinda assumed `shapes : Array(NamedTuple(name: String, area: Int32))`
<FromGitter> <Blacksmoke16> of which there isnt any language feature to know a `NamedTuple(name: String, area: Int32)` is a `Shape` versus a `City` or whatever
<FromGitter> <Blacksmoke16> which is one of the benefits of a struct
<FromGitter> <Blacksmoke16> ☝️ January 7, 2021 6:44 PM (https://gitter.im/crystal-lang/crystal?at=5ff79cdf787d8f79c8ea6cc4) is what we were going off of
<FromGitter> <domgetter> That was just a syntactic example. I don't even have shapes in my code.
<FromGitter> <Blacksmoke16> well theres the disconnect 😆
<FromGitter> <domgetter> I apologize if it wasn't clear that I was originally asking a syntactic question
<FromGitter> <Blacksmoke16> usually when someone asks a question like that its because they have some existing code that they want to use it in
<FromGitter> <Blacksmoke16> but its all good, if you want to share some concrete examples we'd be happy to help
<FromGitter> <Blacksmoke16> but tl;dr structs are better than named tuples, so that point still stands
<FromGitter> <domgetter> Well sure, I do have existing code to use it in, and I can't use that because it doesn't exist
<FromGitter> <Blacksmoke16> so you're not actually using named tuples to pass data around?
<FromGitter> <domgetter> the struct discussion discussion came out of nowhere and wasn't really related to my original quesiton
<FromGitter> <domgetter> I am using a namedtuple in a part of my code, yes
<FromGitter> <domgetter> And I see no reason to change it
<FromGitter> <Blacksmoke16> as you wish
<FromGitter> <Blacksmoke16> it didnt really come out of nowhere tho, when someone mentions named tuples, the answer is usually use a struct
<FromGitter> <Blacksmoke16> are very few use cases for them on their own
<FromGitter> <Blacksmoke16> but if it works for you then 👍
<Andriamanitra> hmm, why do namedtuples exist if you could do the same things with structs?
<FromGitter> <Blacksmoke16> i said very few use cases, not 0 :)
<oprypin> namedtuples exist to pass and receive a set of function args
<FromGitter> <Blacksmoke16> ^
<Andriamanitra> ah, that's a good point
<FromGitter> <Blacksmoke16> i.e. to represent named arguments provided to a function
<FromGitter> <Blacksmoke16> call*
<FromGitter> <Blacksmoke16> they're similar in concept to symbols. I.e. you usually want to use an enum instead
<FromGitter> <Blacksmoke16> that said, atm there's nothing specifically *wrong* about using them, its just not idiomatic and not a best practice
<FromGitter> <Where_Is_X_twitter> hi friends! 🌊 ⏎ ⏎ In the docs for Array#[], I feel that the following regarding end of array is ambiguous: ⏎ ⏎ > "Additionally, an empty array is returned when the starting index for an element range is at the end of the array." [https://gitter.im/crystal-lang/crystal?at=5ff7ac88787d8f79c8ea8ebf]
<oprypin> i guess you're right, but it should be clear with some context
<Andriamanitra> yes it's a bit confusing if that refers to the last element or the index after it but the example explains it
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/a8ia i would have thought this would return `[10, 9, 8]`
<oprypin> Blacksmoke16, that would happen only if array implementation tried to mess with the meaning of a range
<oprypin> a range is always (smaller)..(greater) number
<FromGitter> <Blacksmoke16> you can have ranges like `10..1`
<oprypin> unless you meant `arr[-3..-1]` which works
<oprypin> Blacksmoke16, yes you can and it's empty
<oprypin> >> {(10..1).to_a, (-1..-3).to_a}
<DeBot> oprypin: # => {[], []} - https://carc.in/#/r/a8ig
<FromGitter> <Blacksmoke16> thats a bug imo
<oprypin> no??
<Andriamanitra> not a bug but i could see an argument for changing the behaviour
<FromGitter> <Blacksmoke16> @straight-shoota seemed to suggest `5..1` is a valid range that's supported now
<FromGitter> <Blacksmoke16> but apparently something is up with `to_a`?
<oprypin> i think straight-shoota is wrong there
<oprypin> using #10209 as an argument doesnt work, to me it only makes #10209 seem wrong
<DeBot> https://github.com/crystal-lang/crystal/pull/10209 (Let `Range#step` delegate to `begin.step`) | https://github.com/crystal-lang/crystal/pull/10209 (Let `Range#step` delegate to `begin.step`)
<FromGitter> <Blacksmoke16> whats the downside of having descending ranges?
<FromGitter> <Blacksmoke16> if a range is just a series of values between a start and and end
<oprypin> you can no longer write (0..n) and be able to reason aboout its behavior
<FromGitter> <Blacksmoke16> supporting floats is a diff discussion no?
<FromGitter> <Blacksmoke16> `(10..0).to_a == (0..10).to_a.reverse! # => true` is what im talking about
<oprypin> i know what you're talking about
<oprypin> now actually implement that and watch crystal's specs break
<oprypin> (i'm only guessing)
<FromGitter> <Blacksmoke16> :shrug: cant say i really had a need for it, just that it seems like it should be possible
<oprypin> oh i forgot, you already cant reason about it
<oprypin> if you do `arr[x..6]`, you get a very different behavior if x happens to be -1, which is just off by one from 0
<oprypin> i remember i tried to fight this to make it an error
<oprypin> https://nim-lang.org/docs/system.html#^.t%2Cint is the only way
<FromGitter> <Blacksmoke16> in the context of an array like this im not sure how i feel about it, it would make sense to have it do (given an array 0 to 10), `[10, 0, 1, 2, 3, 4, 5, 6]`
<Andriamanitra> >> (0..10).to_a[-1..6]
<DeBot> Andriamanitra: # => [] - https://carc.in/#/r/a8ip
<Andriamanitra> well, can't say i expected that
<oprypin> so this is the confusion from negative indices. there's also similar confusion from making begin..end interchangeable, i just cant come up with a good example. having them both together is catastrophic, i dont think any language has allowed that to happen
<oprypin> python and ruby and currently crystal has only 1 of them
<Andriamanitra> seems like there's no spec for Array#[negative..positive] and the documentation doesn't say anything about it either
<Andriamanitra> (same goes for String and possibly other types)
<oprypin> Andriamanitra, well documentation assumes some context
<oprypin> -x always means a.size-x
<oprypin> [a.size-x .. positive] should be quite clear, right?
<Andriamanitra> but that's not how it works
<Andriamanitra> or well it kind of is but not the way you'd expect it to
<oprypin> >> a = [0,1,2,3,4,5,6]; {a[-4..5], a[a.size-4 .. 5]}
<DeBot> oprypin: # => {[3, 4, 5], [3, 4, 5]} - https://carc.in/#/r/a8jc
<oprypin> what's not how it works
<Andriamanitra> well i would expect a[-4..0] to give me the last 4
<oprypin> i don't know why :o
<FromGitter> <watzon> I would expect `-4..0` to go from -4 to 0, so I can understand the problem here.
<FromGitter> <watzon> Since there are no negative indexes common sense would dictate that the behavior must be different in arrays, but still
<oprypin> oh wait nevermind
<oprypin> nevermind my link
<oprypin> arrays are just "special"
<Andriamanitra> i don't think it should be changed but it should definitely be documented and tested
<FromGitter> <watzon> Speshul
<oprypin> *first* it wraps around any negative number, then it does whatever other manipulation
<oprypin> i mentioned before, Nim handles it uniquey elegantly, it just has the wraparound as an explicit operation, negative numbers are illegal. https://nim-lang.org/docs/system.html#^.t%2Cint
<FromGitter> <watzon> Nim is just uniquely elegant
<oprypin> ehhh
<FromGitter> <watzon> Well in some cases haha
<oprypin> :>
<Andriamanitra> i don't like symbols having special meanings you "just have to know"
<oprypin> well this is the one situation where it's actually good
<Andriamanitra> big fan of how julia lets you use word "end" in indexing, eg. arr[end-4]
<oprypin> oh yea that is good
<oprypin> wouldnt work so well in crystal - would break every text editor's logic :D
<FromGitter> <3n-k1> i'd like to write a dev tool that analyzes crystal programs' ast, is there a way to hook into the parser without having to manually require internal compiler stuff and manually parse everything?
<oprypin> 3n-k1, no you have to require "compiler/crystal/syntax"
deavmi has joined #crystal-lang
<FromGitter> <Where_Is_X_twitter> I'm in support of documenting the Array[negative..0] and Array[negative..positive] behavior ⏎ ⏎ what is the process of contributing to the standard library docs? would it be a good idea to make an issue and gather opinions on the topic first?
<FromGitter> <Daniel-Worrall> Well you should first work out if it's intentional or not. Since there are no specs to describe the behaviour, it may not be an intended feature and could be open to discussion in an issue
<FromGitter> <Daniel-Worrall> I'd say make an rfc issue on it and lay out what is current behaviour and what could be expected. Put in your opinions. Ask if it should be speced and documented or changed for something else
<oprypin> Daniel-Worrall, i disagree
<oprypin> array behavior is all fully correct and desired. matches Python, at least
<oprypin> adding specs is a possibility
<oprypin> Where_Is_X_twitter, adding docs is one of the few things where not creating an issue first is acceptable. but if you're *not sure* that the docs are lacking, then create an issue
<oprypin> how to do it: create a pull request
<Andriamanitra> i guess a discussion wouldn't hurt but i think changing it would only make it more confusing.. i'd be happy with just getting it documented and speced
<FromGitter> <Where_Is_X_twitter> ^ +1
<FromGitter> <3n-k1> oprypin: oof, thanks. is there any interest in some kind of hook system being added to the compiler? it'd be nice to have an official way to do that so nobody needs to use non-public apis that might break
<oprypin> 3n-k1, too much effort for little gain. the api hasnt broken in very long, anyway
<FromGitter> <Where_Is_X_twitter> also thanks @oprypin
<FromGitter> <3n-k1> oprypin: that's why i said interest, i'd be willing to work on it if there was a chance it would get accepted. i just absolutely do not trust stuff like that to not break *eventually* and i hate that possibility lol
Volk has quit [Quit: See you next time!]
<oprypin> 3n-k1, well, would you also be willing to maintain it for eternity?
<FromGitter> <3n-k1> oprypin: well *hopefully* there would be a way to implement it without any additional maintenance being required except for large breaking changes
<FromGitter> <3n-k1> because otherwise it just wouldn't be worth it, like you said
<FromGitter> <3n-k1> disclaimer: i know absolutely nothing about the compiler's internals lol
<oprypin> all i can tell you is i don't have a good feeling about this, and not a good feeling about it being accepted (though i don't decide). you can do initial investigation, maybe it's very doable, who knows. regarding interest, i haven't heard direct mentions of what you're saying.
<FromGitter> <3n-k1> that's a fair point, no interest means it's useless. i'll check it out, but you're probably right that it's not worth it
<oprypin> i think it's reasonable to expect such an involved project to just keep up with compiler updates
<oprypin> you worry about the API breaking without actual language changes, but you'll still have to deal with actual language changes.
<FromGitter> <3n-k1> that's true. ugh, why is the real world so difficult xd
<oprypin> watzon: let me know if u have any comments on the html produced by mkdocstrings-crystal. i wrote it but https://i.kym-cdn.com/entries/icons/original/000/008/342/ihave.jpg . the main consideration is it has to look ok without any external css (other than material theme's own)
<FromGitter> <watzon> Well you've done a great job then considering
<FromGitter> <watzon> I definitely think it turned out well
<FromGitter> <watzon> I just had a couple changes I wanted, such as having method definitions have a light background color to help break things up a little more, and having the `module` or `class` be a little smaller than the namespace.
f1reflyylmao has joined #crystal-lang
f1refly has quit [Ping timeout: 264 seconds]
alexherbo2 has quit [Ping timeout: 246 seconds]
avane has quit [Quit: ZNC - https://znc.in]
avane has joined #crystal-lang
<FromGitter> <Blacksmoke16> wew i forgot how meh windows was
<FromGitter> <Blacksmoke16> mainly the $ you have to pay to use it :/
<FromGitter> <lunarfyre7> @Blacksmoke16 how do you define a catch all route as a low priority? I tried `"/*"` but it catches everything even from other defined routes
<FromGitter> <Blacksmoke16> whats the use case?
<FromGitter> <lunarfyre7> serving a client html/js blob by default, but responding to api calls
<FromGitter> <Blacksmoke16> i.e. 404 message?
<FromGitter> <lunarfyre7> same idea
<FromGitter> <lunarfyre7> but just serving a front end page by default, letting it do it's thing and start talking to the api
<FromGitter> <Blacksmoke16> mmk, you'd prob be better off defining an exception listener and return that response on 404 exception
<FromGitter> <lunarfyre7> kk
<FromGitter> <Blacksmoke16> i can make an example if you nee
<FromGitter> <lunarfyre7> sure!
<FromGitter> <Blacksmoke16> although i will say that sounds kinda strange :p
<FromGitter> <lunarfyre7> yeah it is a weird thing to do
<FromGitter> <Blacksmoke16> similar to this, but the body would be like
<FromGitter> <Blacksmoke16> er sorry, not that
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ff7ebe6cd31da3d9a9ba424]
<FromGitter> <Blacksmoke16> this would run on all and only 404 exceptions raised in your app
<FromGitter> <Blacksmoke16> which by default is only the routing logic, so :shrug:
<FromGitter> <Blacksmoke16> actually
<FromGitter> <Blacksmoke16> naw thats best you're going to get. I'd maybe rethink if you really need to do that tho
<FromGitter> <lunarfyre7> Cool thanks for the example
<FromGitter> <lunarfyre7> Yeah though I might rethink it :p
<FromGitter> <Blacksmoke16> good :)
<FromGitter> <3n-k1> what does the + mean in `compile-time type is Crystal::ASTNode+`
<FromGitter> <3n-k1> oh no
<FromGitter> <3n-k1> oh hey, at least the thing i wanted to make is literally built into the compiler, ty
<FromGitter> <watzon> @oprypin one thing I've noticed is that types aren't linked inside of method definitions
<FromGitter> <watzon> Would also be a nice to have
_ht has joined #crystal-lang
HumanG33k has quit [Remote host closed the connection]
HumanG33k has joined #crystal-lang
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
<FromGitter> <3n-k1> is there a way to write a macro to iterate over every subclass of a class? not just direct subclasses, but the subclasses of subclasses, etc.
<FromGitter> <3n-k1> that was a stupid question, nvm
<FromGitter> <watzon> @3n-k1 so you figured it out?
<FromGitter> <watzon> Ahh missed that
<FromGitter> <watzon> I really hope the first 1.0 release comes soon
deavmi has quit [Ping timeout: 272 seconds]
deavmi has joined #crystal-lang
hmmm has joined #crystal-lang
Volk has joined #crystal-lang
hmmm has quit [Quit: WeeChat 2.8]
hmmm has joined #crystal-lang
<FromGitter> <lunarfyre7> @Blacksmoke16 when I try your snippet I get this exception: `Error: undefined method 'request=' for Athena::Routing::Events::Exception`
<FromGitter> <lunarfyre7> Also just to clarify what I was talking about a little more just so it seems a little less weird, I was trying to avoid having to use a reverse proxy on the app I'm working on. In Sinatra for example I can use Rack::URLMap to mount my apis under different namespaces, and if none of those match fall back to a default controller that just serves the frontend code. I could actually just run this stuff behind
<FromGitter> ... caddy or something instead and not mess with trying to do it with the backend server, I just really would like to keep more integrated.
hmmm has quit [Quit: WeeChat 2.8]
<FromGitter> <lunarfyre7> an nvm switching to master, and swapping request with response works
deavmi has quit [Ping timeout: 272 seconds]
<FromGitter> <lunarfyre7> oh figured it out
deavmi has joined #crystal-lang
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
HumanG33k has quit [Remote host closed the connection]
HumanG33k has joined #crystal-lang
HumanG33k has quit [Remote host closed the connection]
deavmi has quit [Ping timeout: 272 seconds]
deavmi has joined #crystal-lang
HumanG33k has joined #crystal-lang
HumanG33k has quit [Remote host closed the connection]
HumanG33k has joined #crystal-lang
deavmi has quit [Ping timeout: 272 seconds]
deavmi has joined #crystal-lang
alexherbo2 has joined #crystal-lang
HumanG33k has quit [Ping timeout: 260 seconds]
<hightower2> Hm, small syntax parsing issue, https://carc.in/#/r/a8mk
<FromGitter> <erdnaxeli:cervoi.se> that looks weird, you should probably use parentheses
<FromGitter> <erdnaxeli:cervoi.se> (even if it's also considered as parsing error)
<FromGitter> <naqvis> https://carc.in/#/r/a8mr
<hightower2> yes, yes, sure parens would work... but I was referring to the \ syntax
<hightower2> (which I happen to use much more than parentheses
<FromGitter> <naqvis> Crystal is heavily influenced by Ruby, but Crystal *ain't* ruby :P
<hightower2> yes ruby was just a check...
<hightower2> I'll open a ticket, let's see what the council says :)
<FromGitter> <erdnaxeli:cervoi.se> 👍️
<FromGitter> <naqvis> 👍
HumanG33k has joined #crystal-lang
<FromGitter> <Blacksmoke16> @lunarfyre7 oh sorry, it should have been `event.resposne = ART::Response.new ...`
<FromGitter> <Blacksmoke16> i been thinking about it, it should suffice to define a `ART::Get("*")` route last
alexherbo2 has quit [Read error: Connection reset by peer]
alexherbo2 has joined #crystal-lang
<FromGitter> <Blacksmoke16> given its last it should have the lowest priority, might be worth a shot
alexherbo28 has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 265 seconds]
alexherbo28 is now known as alexherbo2
<FromGitter> <jrei:matrix.org> @Blacksmoke16 may be a good idea to have a Gitter/Matrix channel for Athena
<FromGitter> <Blacksmoke16> https://gitter.im/athena-frameworkcr/community already done :)
<FromGitter> <jrei:matrix.org> Great – so the best place is to talk there ;)
<hightower2> Hm so, once I have a subclass which adds new ivars, if I declare them not nil, I get an error that some of initialize methods (namely the parent class' ones) are leaving it unset, so it can't be not nil.
<FromGitter> <erdnaxeli:cervoi.se> some constructor needs to set them up
<hightower2> Is there a common pattern to work around this, other than creating the same initialize methods in the subclass, to mask the parent ones?
<hightower2> (and other than creating all such ivars as getter!, setter!, of course)
<FromGitter> <Blacksmoke16> no, you cant get around that restriction
<FromGitter> <Blacksmoke16> will need to define the initializer with the same args and super them
<FromGitter> <Blacksmoke16> you *could* use a macro to define the initializer, but you'll need one regardless
<hightower2> hm, pretty nasty, since I don't care about the parent's initialize methods at all, would be useful if there was a way to just ignore/disable them
<hightower2> (I mean, disable for calling directly... calling via super is needed, of course)
<FromGitter> <Blacksmoke16> i mean if you dont care about the parent args dont inherit from it
<hightower2> yes I mean I care, but I want to define just one initialize like initialize(newopt1, newopt2, **parent_opts) and then call super **parent_opts
<hightower2> without having to mask one by one
<FromGitter> <Blacksmoke16> ```def initialize(@child_var : Int32, **parent_args) ⏎ super **parent_args ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5ff86eabcd31da3d9a9cedff]
<FromGitter> <Blacksmoke16> pretty sure that would work
<FromGitter> <Blacksmoke16> assuming you provide `.new` all the required args and none extra
<hightower2> let me try a carc example, I didn't have luck using the approach you just described
<hightower2> can't reproduce... well...
<hightower2> ah, figured why the error is showing up, it's not actually related initializes
<hightower2> but to the fact that the parent object is creating further objects and passing argument parent: self
<hightower2> and if that happens before all non-nil vars are set, the error crops up
<hightower2> I do have a way to work around that, I can just set the value of `parent` later
<hightower2> ok, thanks for the discussion
<sagax> hi all!
<sagax> i am looking for about modules for crystal
<sagax> where i can rich this?
<oprypin> hightower2, regarding your example from 2.5 hours ago, i think Crystal is more technically correct there, and i also think writing it like this is definitely abuse of syntax
<oprypin> why more technically correct: there have been 2 newlines involved but you escaped only 1, so that's just it
<hightower2> oprypin, well, yeah... I find it easier than (), but yeah, fair point
<sagax> no, i am looking for about - where i can found another modules
<sagax> like as gems in ruby
<FromGitter> <Blacksmoke16> oh shards
<FromGitter> <Blacksmoke16> there are a few tools for this
<FromGitter> <Blacksmoke16> https://github.com/veelenga/awesome-crystal and https://shardbox.org/ among others
<sagax> thanks
<sagax> i am start new code with crystal
<sagax> uff
<sagax> i middle in ruby, i think that i middle in ruby,
<sagax> maybe it's help me with crystal
johnny101 has joined #crystal-lang
<FromGitter> <Blacksmoke16> 👍 id suggest reading thru the book if you havent
deavmi has quit [Ping timeout: 272 seconds]
deavmi has joined #crystal-lang
<FromGitter> <erdnaxeli:cervoi.se> there is no way to make a link to an external website in a method's doc? I am implementing a client for an API and I would like to reference the official API documentation.
<FromGitter> <Blacksmoke16> just would be a markdown hyperlink no?
<FromGitter> <erdnaxeli:cervoi.se> oh, sure
<FromGitter> <erdnaxeli:cervoi.se> I tried to just past the raw link
deavmi has quit [Ping timeout: 272 seconds]
deavmi has joined #crystal-lang
<FromGitter> <jrei:matrix.org> dark mode broken on GitHub x)
<FromGitter> <jrei:matrix.org> that's strange, there is a mix of light/dark
<oprypin> jrei:matrix.org, are u sure u dont have a browser extension
<FromGitter> <jrei:matrix.org> no, I checked on both my mobile and my desktop
<FromGitter> <naqvis> its working for me here
<oprypin> oh ya it's super messed up
<FromGitter> <jrei:matrix.org> maybe just a cdn issue
<FromGitter> <naqvis> yeah, might be
<FromGitter> <naqvis> might worth trying after clearing browser cache
<FromGitter> <jrei:matrix.org> ha, looks to be fixed now.
<FromGitter> <jrei:matrix.org> (without doing anything)
<FromGitter> <naqvis> good to know that github isn't windows, where restart fix each and every problem :P
Vexatos has quit [Ping timeout: 240 seconds]
Stephie has quit [Ping timeout: 260 seconds]
deavmi has quit [Ping timeout: 272 seconds]
deavmi has joined #crystal-lang
Stephie has joined #crystal-lang
Vexatos has joined #crystal-lang
Volk has quit [Quit: See you next time!]
deavmi has quit [Ping timeout: 272 seconds]
deavmi has joined #crystal-lang
johnny101 has quit [Quit: ZNC 1.8.1 - https://znc.in]
deavmi has quit [Ping timeout: 272 seconds]
johnny101 has joined #crystal-lang
deavmi has joined #crystal-lang
johnny101 has quit [Quit: ZNC 1.8.1 - https://znc.in]
johnny101 has joined #crystal-lang
<sagax> i have problem with `shards`
<sagax> i try install dependencies https://github.com/Meoowww/Crirc
<sagax> but got `Error shard name (crirc) doesn't match dependency name (Crirc)`
<FromGitter> <Blacksmoke16> can you share your shard.yml?
<straight-shoota> shard names are case sensitive
<straight-shoota> you just have to replace Crirc with crirc in your dependencies
<straight-shoota> *as the name of the dependency
<straight-shoota> I see the shard author got this wrong in the readme
<sagax> wow
<FromGitter> <Blacksmoke16> that would do it 😆
<sagax> yes, i replace `Crirc` to `crirc`
<sagax> thanks!
deavmi has quit [Ping timeout: 272 seconds]
_ht has quit [Remote host closed the connection]
deavmi has joined #crystal-lang
<FromGitter> <watzon> @oprypin this might be asking for too much, but is there any possible way to iterate over definitions within a namespace inside of a doc? For instance, if a module you're talking about has several classes within it and you want to dynamically add a link to each one of those class definitions without doing so manually.
<FromGitter> <watzon> I feel like if there were it would probably require jinja templates or something
<oprypin> watzon, of course it's possible
<oprypin> wait maybe im thinking of something else
<FromGitter> <watzon> Basically what I'm doing here, but dynamically
<FromGitter> <watzon> All of those handlers reside inside of the `Handlers` module
<oprypin> watzon, i mean.. u could semi-abuse mkdocs_gen_files
<oprypin> it's easy if we can assume that this list appears at the end of the document :D
<oprypin> watzon, can u push this btw?
<oprypin> anyway, i think my main reaction is... better just write those out manually
<FromGitter> <watzon> Haha yeah that is something I'm hoping to avoid, but if I could use a plugin like this https://github.com/andyoakley/mkdocs-jinja2 and get access to the mkdocsstrings-crystal data from within the template that could work. I just don't know if I could.
<FromGitter> <watzon> I'll go ahead and push right now, sec
<oprypin> watzon, fwiw this one is more popular https://github.com/fralau/mkdocs_macros_plugin
<FromGitter> <watzon> That could work too
<FromGitter> <watzon> Code is pushed now btw. They should be building in the gh action I have setup.
<oprypin> watzon, completely untested and semi-horrible: https://gist.github.com/647c95a06bf83e7d867d02ad8cf7935c
deavmi has quit [Ping timeout: 272 seconds]
<oprypin> watzon, wow it actually worked first try, other than a trivial typo
deavmi has joined #crystal-lang
Volk has joined #crystal-lang
<FromGitter> <watzon> Do you think it might be at all possible to get access to the `mkdocs_gen_files.config` from within a macro using that macros plugin?
<oprypin> @watzon: probably but that's even more hacky. the config isn't owned by mkdocs_gen_files, it's just the mkdocs config! I'd hope that the macros plugin provides access to mkdocs config
<FromGitter> <watzon> It seems like it does provide access to the config. I'm gonna need to do some testing.
<oprypin> @watzon: o shit it just works!
<oprypin> @watzon: you may not even need to write a .py file (though you might prefer to) maybe you can just straight up write `{% for typ in conf['plugins']` yadda yadda
<FromGitter> <oprypin:matrix.org> > This is object is not accessible as a variable from the markdown pages. Exposing it might encourage black magic.
<FromGitter> <watzon> Mwahahaha
<FromGitter> <watzon> Good thing I'm a wizard
<straight-shoota> nice
<FromGitter> <watzon> We definitely have access to some stuff from within the macros. I guess we'll see what's possible here.
<oprypin> @watzon: plugins.mkdocstrings is what you need
<FromGitter> <watzon> That's what I thought. Right now I'm trying to figure out if I can print that full object to the page so I can inspect it.
<oprypin> @watzon: look in the gen_doc_stubs.py file. that's what you can do with it, just get to the `root`
<FromGitter> <watzon> Managed to iterate over types! This isn't gonna be all that hard actually
<oprypin> watzon, if you did `root.walk_types()` then instead just do this https://gist.github.com/oprypin/647c95a06bf83e7d867d02ad8cf7935c#file-gen_doc_stubs-py-L3
<oprypin> watzon, hold up, does the macros plugin complain about {%begin%} in crystal code? how did you pass that?
<FromGitter> <watzon> I wrapped the code block with `{% raw %} {% endraw %}`
postmodern has joined #crystal-lang
<oprypin> watzon, that's gonna be annoying as heck
<FromGitter> <watzon> It'll happen very rarely. I won't be documenting macro internals often.
<FromGitter> <watzon> It would be nice if there was a setting to just ignore code blocks though
<oprypin> watzon, u probably already figured out but https://gist.github.com/647c95a06bf83e7d867d02ad8cf7935c
<oprypin> omg
<oprypin> how about *just* `{% for typ in crystal.lookup('Tourmaline::Handlers').types %}`
<FromGitter> <watzon> Just realized I need to do a little filtering since each off those types also has a `Context` type defined within them, but I think I got it
<oprypin> watzon, are you not looking at the examples i'm sending o.o what do you have now?
<FromGitter> <watzon> I ended up just defining the logic in a `main.py` file to keep it out of the templates. I ended up with this: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ff8e7fc99549911fc0ded1d]
<FromGitter> <watzon> I could definitely simplify this, but it's working so far
<FromGitter> <watzon> Then in the template I just do this ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ff8e825d5f4bf2965d5022a]
deavmi has quit [Ping timeout: 272 seconds]
<FromGitter> <watzon> And end up with this
<oprypin> watzon, just `return root.lookup(kind).types`
<FromGitter> <watzon> The only problem with just returning that is that I need to filter out the `Context` types. `root.lookup(kind).types` returns types like `Tourmaline::Handlers::CommandHandler::Context`
<oprypin> watzon, no
<FromGitter> <watzon> I can definitely simplify things by using python's `filter()` method though
<FromGitter> <watzon> Ohhhh wait
<FromGitter> <watzon> `types` and not `walk_types()`
<FromGitter> <watzon> Duh haha. That works.
<oprypin> @watzon
deavmi has joined #crystal-lang
<oprypin> straight-shoota, are u seeing this
<straight-shoota> didn't follow the discussion
<oprypin> straight-shoota, just look at the diff https://gist.github.com/647c95a06bf83e7d867d02ad8cf7935c
<oprypin> *this* is now possible
<sagax> why i got `Error: undefined method 'bind_tcp' for Nil (compile-time type is (HTTP::Server | Nil)`
<sagax> ?
<oprypin> sagax, @server might be nil
<oprypin> sagax, just read the whole docs, but this is https://crystal-lang.org/reference/syntax_and_semantics/if_var_nil.html
<sagax> yes, but i declare @server variable in `create_server`
<FromGitter> <watzon> Wonderfully done @oprypin
<FromGitter> <watzon> 👏
<oprypin> watzon, thanks for the amazing ideas
<FromGitter> <watzon> Thanks for working with me to make them happen. That was great.
<oprypin> just the perfect early access user :D
<sagax> don't understand
<sagax> i read, but don't understand where i have fault
<FromGitter> <watzon> I could be the nightmare early access user lol. I am always thinking of niche features I wish existed.
<straight-shoota> oprypin, I get the diff, but what do a.jinja and gen_doc_stubs do?
<oprypin> straight-shoota, nothing, not related, sorry
<straight-shoota> aah
<straight-shoota> that placeholder substitution looked really out of the way with jinja templates in the other file
<FromGitter> <watzon> And now I can do this as well
<sagax> add check that `@server` nil
<sagax> but have errors anyway
<straight-shoota> sagax, the fault is that you call `@server.bind_tcp` but @server can be nil and then you can call nothing on it
<FromGitter> <watzon> Were it just going to be a single module that I needed to manually write out the types for I probably would've just left it, but I really hate duplicating processes
<oprypin> u can do `if (server = @server); use server;`
<straight-shoota> why is @server nilable anyways?
<straight-shoota> I don't know your use case, but it might be better to just have it not-nilable
<straight-shoota> either initialize the ivar in the constructor or lazily
<oprypin> watzon, btw you could also just render all of the api documentations of all those classes on one page
<FromGitter> <watzon> Yep, or create a nice big ToC if I wanted haha. I like this use case though. It suits my purposes well.
<oprypin> ok :)
<sagax> hm
<sagax> if i declare @server in initialized method - all done
<oprypin> whether i like it or not, seems like almost nobody will be putting multiple items on the same page xD
<oprypin> sagax, yes, then @server is not a nilable type
<sagax> but if i declare @server in class method after initialize class to variable - @server have strange
<sagax> what different between - declare variable in initialize method or just something method?
<oprypin> sagax, the difference is the compile-time type of the variable. in one case it can be nil, in the other case it can never be nil
<oprypin> and when you're trying to call any method on @server, regardless of its current runtime type, the compiler prevents you from doing it because the compile-time type is `HTTP::Server | Nil`
<sagax> how to be sure that the variable is declared when some method have done?
<straight-shoota> there's no way to do that
<oprypin> make an accessor method that does ||=
<oprypin> `private def server; server ||= HTTP::Server.new; end` and use `server` instead of `@server`
<oprypin> there's a shorthand for writing this:
<oprypin> `getter server do; HTTP::Server.new; end`
<sagax> hm,
<sagax> ok, thanks
<sagax> i need read more about `getter` and module/class-variables and methods
<oprypin> correction for the above:
<oprypin> `private def server; @server ||= HTTP::Server.new; end`
<oprypin> i sure hope that works :/
<sagax> heh, crystal have `not_nil!` method to call method if variable declared that type can be nil
<sagax> and `@server.not_nil!.bind_tcp` all done, and @server not declared in `initialized` and have type with `?`