ChanServ changed the topic of #crystal-lang to: The Crystal programming language | https://crystal-lang.org | Fund Crystal's development: https://crystal-lang.org/sponsors | GH: https://github.com/crystal-lang/crystal | Docs: https://crystal-lang.org/docs | Gitter: https://gitter.im/crystal-lang/crystal
hendursa1 has quit [Quit: hendursa1]
hendursaga has joined #crystal-lang
andremedeiros has quit [Quit: ZNC 1.8.2 - https://znc.in]
andremedeiros has joined #crystal-lang
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
_ht has joined #crystal-lang
ua_ has quit [Ping timeout: 245 seconds]
ua_ has joined #crystal-lang
postmodern has quit [Quit: Leaving]
<FromGitter> <erdnaxeli:cervoi.se> `Process.run` is better, thanks
hendursa1 has joined #crystal-lang
hendursaga has quit [Ping timeout: 240 seconds]
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
sagax has joined #crystal-lang
alexherbo2 has joined #crystal-lang
alexherbo20 has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 240 seconds]
alexherbo20 is now known as alexherbo2
sagax has quit [Ping timeout: 252 seconds]
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
sagax has joined #crystal-lang
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
yxhuvud has quit [Quit: No Ping reply in 180 seconds.]
yxhuvud has joined #crystal-lang
<FromGitter> <alexherbo2> hello
<FromGitter> <alexherbo2> I have a question about some of the convention, I asked on #ruby but I think it is also applicable here
<FromGitter> <alexherbo2> when you do `extend self` (https://crystal-lang.org/reference/syntax_and_semantics/modules.html#extend-self)
<FromGitter> <alexherbo2> you then refer in specs as `#method_name` or as `.method_name`?
<yxhuvud> I'd say the latter.
<FromGitter> <alexherbo2> also for initialized, should we test `#new` or `.new`?
<FromGitter> <alexherbo2> `initialize`*
<FromGitter> <naqvis> so `extend self` in module is same as you prepending `self.methodname` for all methods
<FromGitter> <naqvis> also `initialize` is a special method used for initialization of state which is invoked by compiler generated `self.new` method
<FromGitter> <naqvis> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=60801ebc55d78266a65b15b4]
f1refly has joined #crystal-lang
alexherbo27 has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 245 seconds]
alexherbo27 is now known as alexherbo2
andremedeiros has quit [Read error: Connection reset by peer]
<FromGitter> <alexherbo2> @naqvis so in `spec` you refer as `.method_name` and `#new`?
<FromGitter> <naqvis> yeah
andremedeiros has joined #crystal-lang
<FromGitter> <naqvis> `self.method` is what is known as class methods
<FromGitter> <alexherbo2> but why `#new`, as the method is called on the class, rather than an instance?
<FromGitter> <naqvis> so you don't need to have an instance to access class methods
<FromGitter> <naqvis> either Module.method or `Class.method` (when they are declared as `self.method`)
<FromGitter> <Blacksmoke16> it should be `".new"` in specs
<FromGitter> <Blacksmoke16> as it is a class method and you dont interact directly with initialize
<FromGitter> <Blacksmoke16> but it could be `"#method_name"` or `.method_name` depending on if its a class or instance method
<FromGitter> <Blacksmoke16> as @naqvis pointed out
<FromGitter> <alexherbo2> thanks
<FromGitter> <alexherbo2> I figured out by looking at https://crystal-lang.org/api/1.0.0/Hash.html and searching for `new` referred indeed as `.new`
<FromGitter> <Blacksmoke16> > also `initialize` is a special method used for initialization of state which is invoked by compiler generated `self.new` method ⏎ ⏎ as @naqvis said
<FromGitter> <alexherbo2> @Blacksmoke16 so for methods in a module extended with `extend self`, what do you write in spec to refer them?
<FromGitter> <Blacksmoke16> you'd have to use `.`
<FromGitter> <Blacksmoke16> assuming the module is just being used as a namespace to store those methods
<FromGitter> <Blacksmoke16> like if you're intending to use the methods like `TheModule.the_method` use `.`, but if you're intending on including the module in another type then you'd prob use `#the_method` as it would be in the context of an obj instance
<FromGitter> <alexherbo2> the thing is an `extend self` can be both no?, we can directly call `TheModule.the_method` or `the_method` when `include TheModule`
<FromGitter> <Blacksmoke16> yea, depends on what context you intend to use the method
<FromGitter> <Blacksmoke16> prob doesnt really matter too much
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
<FromGitter> <RespiteSage> Is there a way to reserve capacity in an already-constructed `Array`? I'm not seeing any methods in the docs.
<FromGitter> <Blacksmoke16> i.e. resize the array manualy?
<FromGitter> <Blacksmoke16> doesnt look like it w/o creating another
<FromGitter> <Blacksmoke16> could you give it an initial capacity when initializing it?
<FromGitter> <RespiteSage> I can rearrange the code to do that, probably.
<FromGitter> <elementio:salt-rock-lamp.ems.host> is there a clear explanation anywhere in the crystal docs of "<" vs "extends" vs "includes"? i don't have a ruby background so i don't know if this is considered common/basic knowledge in the ruby world.
<FromGitter> <erdnaxeli:cervoi.se> "<" is classic object inheritance
<FromGitter> <erdnaxeli:cervoi.se> for extend vs include : https://crystal-lang.org/reference/syntax_and_semantics/modules.html
<FromGitter> <Blacksmoke16> `<` in inheritance akin to `extends` in some other languages, while `extends` and `includes` are composition, like traits in PHP
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
<FromGitter> <elementio:salt-rock-lamp.ems.host> @Blacksmoke16 i'm not familiar with PHP's OO system either - can you elaborate?
<FromGitter> <Blacksmoke16> what language are you coming from?
<FromGitter> <elementio:salt-rock-lamp.ems.host> straight-shoota that was my question :) i should have been more open with "what i already know" instead of just asking. but i don't think either my self answer (just quoting the docs) or the other answer helped me understand the full thing. i will ask a separate question that i can either self-answer or hopefully someone else will answer.
<FromGitter> <elementio:salt-rock-lamp.ems.host> @Blacksmoke16: among general-purpose languages that support OO, i am most experienced with python.
<FromGitter> <erdnaxeli:cervoi.se> so extending a module makes class methods, while including it makes instance methods
<FromGitter> <elementio:salt-rock-lamp.ems.host> oh, inclusion is also for modules?
<FromGitter> <elementio:salt-rock-lamp.ems.host> i thought it was for classes
<FromGitter> <erdnaxeli:cervoi.se> inclusion is only for module, I don't think you can includes a class
<FromGitter> <erdnaxeli:cervoi.se> you inherites from a class using "<"
<FromGitter> <erdnaxeli:cervoi.se> like in python
<FromGitter> <erdnaxeli:cervoi.se> except in crystal there is not multi inheritance like in python
<FromGitter> <elementio:salt-rock-lamp.ems.host> right, and i believe inheritance with `<` is also present in ruby?
<FromGitter> <Blacksmoke16> modules are for composition AND namespacing. Modules can be included/extended into other types (classes, structs, or other modules)
<FromGitter> <Blacksmoke16> yes
<FromGitter> <erdnaxeli:cervoi.se> yep, those concepts (include, exclude, modules) come from ruby
<FromGitter> <elementio:salt-rock-lamp.ems.host> aha. ok this makes more sense
<FromGitter> <Blacksmoke16> modules are also the way you can define pseudo interfaces
<FromGitter> <Blacksmoke16> ```module SomeInterface ⏎ abstract def name : String ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=60804610b9e6de24d64c32a4]
<FromGitter> <elementio:salt-rock-lamp.ems.host> i see, anything implementing that interface would include or extend the module that defines the interface
<FromGitter> <erdnaxeli:cervoi.se> coming from python too, the namespacing think was one of the hardest thing to understand when doing crystal
<FromGitter> <erdnaxeli:cervoi.se> while in python you would define a module (which is juste a file) or a package (which is a folder), there are no such think in crystal
<FromGitter> <erdnaxeli:cervoi.se> instead you define a module for namespacing
<FromGitter> <Blacksmoke16> you cant have abstract class methods in crystal (atm?), so mainly need them for instance based methods
<FromGitter> <erdnaxeli:cervoi.se> and you can define all you function, classes, structs, other modules, inside this module
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=608046bbb6a4714a29db0582]
<FromGitter> <elementio:salt-rock-lamp.ems.host> so *practically* what's the difference between a module and a class? a module cannot be instantiated, but a class can?
<FromGitter> <erdnaxeli:cervoi.se> exactly
<FromGitter> <elementio:salt-rock-lamp.ems.host> they both can have instance variables?
<FromGitter> <Blacksmoke16> yes, but you wouldnt be able to use them w/o including it into another type
<FromGitter> <Blacksmoke16> and fwiw a class/struct can also be used as a namespace
<FromGitter> <Blacksmoke16> ```class SomeClass ⏎ record NestedType ⏎ end ⏎ ⏎ SomeClass::NestedType.new``` [https://gitter.im/crystal-lang/crystal?at=60804710ae90f36840958239]
<FromGitter> <erdnaxeli:cervoi.se> a module can only have class variable, with @@, which are global
<FromGitter> <elementio:salt-rock-lamp.ems.host> and the difference between a class and struct is that the former is passed by reference and the latter by value (and as such can be stack allocated)?
<FromGitter> <erdnaxeli:cervoi.se> yep
<FromGitter> <elementio:salt-rock-lamp.ems.host> oh, modules dont have instance variables like `@x`? only class variables `@@x`?
<FromGitter> <Blacksmoke16> > a module can only have class variable, with @@, which are global ⏎ ⏎ Pretty sure this isn't true, see https://play.crystal-lang.org/#/r/ay5p
<FromGitter> <elementio:salt-rock-lamp.ems.host> if in a class i `include` a module that refers to `@@x` in the module, does that become a `@x` in the class?
<FromGitter> <erdnaxeli:cervoi.se> yeah, it works if you include the module
<FromGitter> <Blacksmoke16> a module on its own can only have class ones yes, but you can totally define ivars in a module to share them (and additional methods) in various other types
<FromGitter> <erdnaxeli:cervoi.se> but this does not work : https://play.crystal-lang.org/#/r/ay5q
<FromGitter> <Blacksmoke16> no, they'd still be separate
<FromGitter> <Blacksmoke16> right, that makes sense
<FromGitter> <Blacksmoke16> a module on its own cant use ivars, has to be included in another type
<FromGitter> <naqvis> @erdnaxeli:cervoi.se you can not access instance variables inside class methods
<FromGitter> <erdnaxeli:cervoi.se> true
<FromGitter> <Blacksmoke16> but i dont think it was entirely accurate to say "modules can only have class vars"
<FromGitter> <Blacksmoke16> as you *can* have ivars too, but with limitations
<FromGitter> <erdnaxeli:cervoi.se> yes
<FromGitter> <erdnaxeli:cervoi.se> https://play.crystal-lang.org/#/r/ay5u why this does not work?
<FromGitter> <erdnaxeli:cervoi.se> i wanted to test if @@value was the same for Foo and Bar
<FromGitter> <Blacksmoke16> pretty sure class vars/methods aren't included when doing `include`
<FromGitter> <erdnaxeli:cervoi.se> ah, right
<FromGitter> <erdnaxeli:cervoi.se> only methods are
<FromGitter> <Blacksmoke16> well but based on the error it seems it knows about it
<FromGitter> <Blacksmoke16> is possible it's just a bug or something, modules make my brain hurt sometimes lol
<FromGitter> <elementio:salt-rock-lamp.ems.host> > Error: @instance_vars are not yet allowed in metaclasses: use @@class_vars instead
<FromGitter> <elementio:salt-rock-lamp.ems.host> hm
<FromGitter> <Blacksmoke16> right
<FromGitter> <Blacksmoke16> you cant get an instance of a module, so that makes sense
<FromGitter> <erdnaxeli:cervoi.se> if you use an instance var in a module's function it must be included in order to be used
<FromGitter> <Blacksmoke16> ^
<FromGitter> <erdnaxeli:cervoi.se> I am confused: https://play.crystal-lang.org/#/r/ay6f
<FromGitter> <erdnaxeli:cervoi.se> ah, you never have the class method (self.xyz) defined in a module be accesible in a type including or extending it
<FromGitter> <Blacksmoke16> `class_property` defines `self.value` getter and setter
<FromGitter> <Blacksmoke16> yea, `extend` only makes instance method in the module as class methods
<FromGitter> <erdnaxeli:cervoi.se> yep
<FromGitter> <erdnaxeli:cervoi.se> https://play.crystal-lang.org/#/r/ay6i <= this is wrong but helps me understand
<FromGitter> <erdnaxeli:cervoi.se> I think I actually never used "extend"
<FromGitter> <erdnaxeli:cervoi.se> in real code
<FromGitter> <erdnaxeli:cervoi.se> so yeah, salt rock lamp, just use module for namespacing, interfaces with abstract methdo, or simple mixin patterns :D
<FromGitter> <Blacksmoke16> yea i cant say i have either
<FromGitter> <elementio:salt-rock-lamp.ems.host> makes sense, but i dont think i understand how the scoping and instance/class variable stuff works yet
<FromGitter> <elementio:salt-rock-lamp.ems.host> ```code paste, see link``` ⏎ ⏎ this is the example from the docs [https://gitter.im/crystal-lang/crystal?at=60804ab006e2e024e869546a]
<FromGitter> <elementio:salt-rock-lamp.ems.host> what is `items`?
<FromGitter> <Blacksmoke16> `self.items`, it assumes the including type has a method called `items`
<FromGitter> <Daniel-Worrall> Meaningless until it is included
<FromGitter> <elementio:salt-rock-lamp.ems.host> i see. and what if i define a top-level `items` function but don't define it in the include-ing class?
<FromGitter> <Blacksmoke16> pretty sure it wouldnt work
<FromGitter> <Daniel-Worrall> Crystal only compiles code that is run. Modules aren't compiled unless they are included and/or ran
<FromGitter> <erdnaxeli:cervoi.se> actually it does work: https://carc.in/#/r/ay6q
<FromGitter> <naqvis> > https://play.crystal-lang.org/#/r/ay5u why this does not work? ⏎ ⏎ I would say this should be a bug, class vars are included as well, but accessing them like this is treating them as re-definition
<FromGitter> <Daniel-Worrall> Yeah, it just runs that code from the callsite. Top level would be ran when included without the definition in the include-ing class
<FromGitter> <Blacksmoke16> oh, i suppose that makes sense
<FromGitter> <erdnaxeli:cervoi.se> naqvis (Ali Naqvi): weird
<FromGitter> <Daniel-Worrall> A way to avoid global definitions breaking intentions from inclusions would be to use `self.method` https://carc.in/#/r/ay6u
<FromGitter> <elementio:salt-rock-lamp.ems.host> huh, that scoping with implicit `self` is kind of hairy
<FromGitter> <elementio:salt-rock-lamp.ems.host> seems like a footgun waiting to happen if you aren't diligent about using `self`
<FromGitter> <Daniel-Worrall> The solution would be don't polute your global scope :)
<FromGitter> <erdnaxeli:cervoi.se> most of the time I have only one class or module per file, without any thing at top level, so that's ok
<FromGitter> <erdnaxeli:cervoi.se> and then, tests should catch it
<FromGitter> <Daniel-Worrall> and you probably will run into a case where the method signatures are different
<FromGitter> <Daniel-Worrall> Getting into the habit of typing your parameters and returns helps
<FromGitter> <naqvis> i use modules as interface and declaring abstract methods inside ensures you follow the signature when you include them
<FromGitter> <elementio:salt-rock-lamp.ems.host> i get that the typical file structure might make it a non-issue in most cases, but i guess it just makes me squirm. ⏎ ⏎ for example, the (very minimal clone of) api for a popular http client in python: ⏎ ⏎ ```code paste, see link``` ... [https://gitter.im/crystal-lang/crystal?at=60804ea0b6a4714a29db1d68]
<FromGitter> <Blacksmoke16> im sure its a real problem, but in practice it's mitigated by how Crystal structures its code
<FromGitter> <elementio:salt-rock-lamp.ems.host> or worse, consider the opposite situation: where you define a module that refers to something that should be an instance method, but the user never implements that method, and instead there (by accident or by design) is a top-level function of the sam ename
<FromGitter> <Blacksmoke16> how you should structure your code*
<FromGitter> <Blacksmoke16> defining top level methods like that is a smell anyway
<FromGitter> <elementio:salt-rock-lamp.ems.host> as opposed to inside a module?
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=60804f46dc24646812d5eba2]
<FromGitter> <Blacksmoke16> you should ideally namespace your types and stuff
<FromGitter> <Blacksmoke16> otherwise there's nothting preventing like: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=60804f8b97cf50674676e257]
<FromGitter> <elementio:salt-rock-lamp.ems.host> right, that's precisely my qualm :)
<FromGitter> <Blacksmoke16> personally i cant say i ever ran into that, only app i really know of that does top level stuff is kemal tbh
<FromGitter> <elementio:salt-rock-lamp.ems.host> hm... is `@x` the same as `self.x` then?
<FromGitter> <Blacksmoke16> no
<FromGitter> <Blacksmoke16> `@x` is accessing the ivar directly. `self.x` is calling a method that returns the value of `@x`
<FromGitter> <Blacksmoke16> ```def x ⏎ @x ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=6080500655d78266a65bb019]
<FromGitter> <Blacksmoke16> which is created for you if you did like `getter x : Int32` or `property x : Int32`
<FromGitter> <elementio:salt-rock-lamp.ems.host> ah
<FromGitter> <elementio:salt-rock-lamp.ems.host> i see, so there's no way to *directly* access an instance variable from outside the class, unlike e.g. python (which i know is a bit weird w. respect to its class/OO design)
<FromGitter> <elementio:salt-rock-lamp.ems.host> hence the need for getter/setter/property
<FromGitter> <Blacksmoke16> welllll there is but you shouldnt do it
<FromGitter> <naqvis> you can do that, but please DON'T
<FromGitter> <Blacksmoke16> and im not going to tell you how :P
<FromGitter> <naqvis> Encapsulation need to be followed :P
<FromGitter> <erdnaxeli:cervoi.se> the pattern is to use getter/setter/property
<FromGitter> <erdnaxeli:cervoi.se> unlike python where everything is public
<FromGitter> <Blacksmoke16> or define the getter/setter yourself if it needs custom logic
<FromGitter> <erdnaxeli:cervoi.se> yes
<FromGitter> <Daniel-Worrall> Crystal lets you shoot yourself in the foot, just like most languages, but we'll always encourage you not to
<FromGitter> <elementio:salt-rock-lamp.ems.host> @Blacksmoke16: is the `::` in `MyHTTPClient::ClientSession` just part of the name? or is it something syntactically special?
<FromGitter> <Blacksmoke16> it's used to separate the namespaces the type is actually located
<FromGitter> <Blacksmoke16> i.e. the FQN
<FromGitter> <Blacksmoke16> so its saying `ClientSession` exists in the `MyHTTPClient` type
<FromGitter> <Blacksmoke16> like other langs namespacing allows you to have two types with the same name among other things
<FromGitter> <Blacksmoke16> mainly to prevent conflicts, like if you're making a shard all your types should be in a like `MyApp` namespace
<FromGitter> <elementio:salt-rock-lamp.ems.host> yeah i understand its purpose. i was wondering if it was some kind of syntax that the compiler recognized, or just a convention for developers to use
<FromGitter> <elementio:salt-rock-lamp.ems.host> it looks like i can't name a top-level method `a::b` for example
<FromGitter> <Blacksmoke16> right, it's just for types
<FromGitter> <Blacksmoke16> although there is syntax like `::SomeType`
<FromGitter> <Blacksmoke16> or `::my_method`
<FromGitter> <elementio:salt-rock-lamp.ems.host> that bypasses looking within the current class/module and looks only in the surrounding scope. right?
<FromGitter> <elementio:salt-rock-lamp.ems.host> so "the program" there means truly top level?
<FromGitter> <Blacksmoke16> yea
<FromGitter> <elementio:salt-rock-lamp.ems.host> got it
<FromGitter> <elementio:salt-rock-lamp.ems.host> i assume nesting modules is considered bad practice then?
<FromGitter> <Blacksmoke16> not really
<FromGitter> <Blacksmoke16> can be useful for grouping related types
<FromGitter> <Blacksmoke16> or segregating a type so that another namespace may also define a type with the same name
<FromGitter> <Daniel-Worrall> That part should be changed. A bit confusing to end the sentence with "`::`:"
<FromGitter> <Daniel-Worrall> 3 colons
<FromGitter> <Daniel-Worrall> In fact, I think most or all of codeblocks should avoid being placed next to punctuation.
<FromGitter> <Daniel-Worrall> Just for clarity and readability
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
DTZUZU has quit [Read error: Connection reset by peer]
alexherbo2 has quit [Ping timeout: 246 seconds]
DTZUZU has joined #crystal-lang
alexherbo2 has joined #crystal-lang
maxpowa has quit [Ping timeout: 248 seconds]
maxpowa has joined #crystal-lang
_ht has quit [Remote host closed the connection]
alexherbo2 has quit [Ping timeout: 260 seconds]
alexherbo2 has joined #crystal-lang
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
alexherbo21 has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 240 seconds]
alexherbo21 has quit [Ping timeout: 265 seconds]
alexherbo2 has joined #crystal-lang