<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> 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>
<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>
<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> 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]`
<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
<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"
<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.
<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>
<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> 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]
<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
<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
<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.
<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, 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.
<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> 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()`
<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