<FromGitter>
<riffraff169> hmmm....i see....i like to understand these things rather than just use them....what would be advantages or disadvantages be?
<FromGitter>
<Blacksmoke16> you get more type safety and easier to interact with
<FromGitter>
<riffraff169> immutable, that is good, none of my tokens will need to change after being created
<FromGitter>
<Blacksmoke16> i.e. `lexeme.type` etc
<FromGitter>
<Blacksmoke16> is the type of `value` going to be different for each oen?
<FromGitter>
<riffraff169> i put in a ticket/issue with the error above still...i will change my code to use a record/struct
<FromGitter>
<riffraff169> value will have 3 different types, either a string, symbol, or int32 (maybe 64)
<FromGitter>
<riffraff169> so could make an array of records
<FromGitter>
<Blacksmoke16> and what about `type`?
<FromGitter>
<riffraff169> type will always be a symbol specifying the type of the token, like :comma, :string, :lessthan, etc
<FromGitter>
<riffraff169> `:value` will be the value of the token, `:line` will be current line number for the token
<FromGitter>
<riffraff169> not tracking columns yet
<FromGitter>
<oprypin:matrix.org> @riffraff169: i'd even consider `abstract struct Token`
<FromGitter>
<riffraff169> i have never used abstract classes/structs in ruby/crystal, how would i use that properly? docs on it somewhere?
<FromGitter>
<oprypin:matrix.org> @riffraff169: could you just provide some kind of overview what kind of items they could be?
<FromGitter>
<Blacksmoke16> an enum might also be a good idea
<FromGitter>
<oprypin:matrix.org> i see both `:type => :pragma, :value => :token` and `:type => :pragma, :value => "string"`, why is it that it can be both a symbol and a string, how are you going to deal with the usage?
<FromGitter>
<riffraff169> a specific token cant be both, but a token will have a type and a value....so a `:word:` type could have a value of `thisvar` `i`, etc, like variable names
<FromGitter>
<riffraff169> a `:number` type will be 10, 1.7, etc
<FromGitter>
<riffraff169> basically im just tokenizing
<FromGitter>
<oprypin:matrix.org> well great then
<FromGitter>
<oprypin:matrix.org> make use of the type system
<FromGitter>
<riffraff169> im definitely open to suggestions, this is my first crystal program
<FromGitter>
<Blacksmoke16> would a number actually be a `Number` type, or wouldnt they just be `String`?
<FromGitter>
<Blacksmoke16> unless you're value conversion as well
<FromGitter>
<oprypin:matrix.org> oh .. yea thats a good point i guess
<FromGitter>
<riffraff169> yes, im parsing hex `$`, octal `0`, and binary `%` and converting to decimal for storage
<FromGitter>
<oprypin:matrix.org> i think typically that isn't being done (because the integer type has its limit and maybe you don't want to run into it in the early stages of parsing)
<FromGitter>
<riffraff169> normally that would be a problem, but my specific use case is parsing for 6502 assembly, which basically has a 16bit limit (high-byte, low-byte), so i have no overflow problems
<FromGitter>
<riffraff169> ok, i see....im at really early stages, basically just this lexing is all i have right now...not even parsing yet...so definitely open to suggestions
<FromGitter>
<riffraff169> so i would define `lexemes = [] of Token`
<FromGitter>
<riffraff169> which would cover all the subclasses
<FromGitter>
<Blacksmoke16> yup
<FromGitter>
<riffraff169> great, that would make it easier...now, i would do something like:
<FromGitter>
<riffraff169> ```case token ⏎ when NumberToken ⏎ when WordToken``` ⏎ ⏎ to differentiate between them, and not try to access a type incorrectly (number will have Int32, word will have String) [https://gitter.im/crystal-lang/crystal?at=605b47d9563232374c3ef9de]
<FromGitter>
<riffraff169> groovy, thanks for the suggestions....ill go from here and see what happens
<FromGitter>
<riffraff169> `in`, not `when` ?
<FromGitter>
<Blacksmoke16> that would be a compile time error if you added a new token type and wouldnt be checking for it
<FromGitter>
<oprypin:matrix.org> the difference is only an exhaustiveness check
<FromGitter>
<Blacksmoke16> assuming you want to check all types versus just a few
<FromGitter>
<riffraff169> ah....well, after looking at rust and some other languages, im kind of looking at the exhaustiveness....that would make sure i wouldnt have any unhandled types
<FromGitter>
<riffraff169> this actually makes me make my tokens more orthogonal too...better, thanks
<FromGitter>
<Blacksmoke16> 👍
yxhuvud has quit [Read error: Connection reset by peer]
<FromGitter>
<riffraff169> thanks...i should know this....i did think there might be a default constructor, or a default value....thanks
<FromGitter>
<oprypin:matrix.org> @riffraff169: it is in fact hard to know, no worries
<FromGitter>
<riffraff169> cool thanks, ill memorize it now
<FromGitter>
<straight-shoota> yeah, an abstract class shouldn't complain over missing ivar initialization
<FromGitter>
<straight-shoota> or abstract struct
hightower2 has quit [Ping timeout: 246 seconds]
<FromGitter>
<riffraff169> ok cool, got some sample code built and running, so thats good...
<FromGitter>
<riffraff169> wondering, how would one implement something like rusts enum types? those enums can have values....this is sort of like that i think
<FromGitter>
<Blacksmoke16> the values can only be integers tho
<straight-shoota>
enum types in Rust are different
<FromGitter>
<riffraff169> yeah
<FromGitter>
<oprypin:matrix.org> @riffraff169: the closest is indeed abstract struct
<straight-shoota>
Crystal equivalent would be a union type
<FromGitter>
<riffraff169> yeah, thats what it looks like
<straight-shoota>
or abstract struct
<FromGitter>
<riffraff169> yeah, like c union but where it knows what type it is
<FromGitter>
<riffraff169> cool thanks
<FromGitter>
<riffraff169> what would be the best way to convert a String to a symbol? ruby has `.to_sym`...or is there something better to do?
<FromGitter>
<oprypin:matrix.org> @riffraff169: you just don't do it
<FromGitter>
<riffraff169> ok
<FromGitter>
<oprypin:matrix.org> @riffraff169: if you really actually get user input as a string, and it always happens to match, this is the way https://crystal-lang.org/api/1.0.0/Enum.html#parse(string:String):self-class-method
<FromGitter>
<riffraff169> interesting, yeah, that wont quite work i think....ill just use a string and use string comparisons
<FromGitter>
<oprypin:matrix.org> @riffraff169: the officially approved usage of symbols is limited to "the thing that serves as the key in a namedtuple", and the officially approved usage of namedtuple is limited to "the thing that stores named arguments to a function". symbols just aren't liked
<FromGitter>
<riffraff169> ah
<FromGitter>
<oprypin:matrix.org> although technically they do work fine in quite many situations
<FromGitter>
<riffraff169> as im sure you know, in ruby they are preferred because `:thing` is always the object, whereas `"thing"` could be different objects
<FromGitter>
<riffraff169> but that is fine
<FromGitter>
<riffraff169> at least, thats how i understood it
<FromGitter>
<oprypin:matrix.org> in crystal it's just SomeEnum::Thing
<FromGitter>
<oprypin:matrix.org> and for fully runtime handling you just have to use string
<FromGitter>
<riffraff169> yeah...can you add enums to an enum dynamically?
<FromGitter>
<Blacksmoke16> no
<FromGitter>
<oprypin:matrix.org> no
<FromGitter>
<riffraff169> ok, ill just use strings, thanks
<FromGitter>
<oprypin:matrix.org> if the set of valid strings is limited to particular compiletime values, then that's just Enum.parse again
<FromGitter>
<riffraff169> i just probably use that....the set of acceptable words will be limited, so that should be easy
<FromGitter>
<oprypin:matrix.org> and i haven't explicitly said this -- you really can't convert to symbol. they must be known at compile time
<FromGitter>
<riffraff169> yeah, that makes sense
<FromGitter>
<riffraff169> part of the compile time checking
<FromGitter>
<riffraff169> even though crystal looks like ruby, still more like c i think...i will have to adjust my thinking
<FromGitter>
<oprypin:matrix.org> i wouldn't call it "checking", it's an implementation requirement
<FromGitter>
<riffraff169> now i like c, so not a problem
<FromGitter>
<oprypin:matrix.org> symbols are like a special globally shared enum :>
<FromGitter>
<riffraff169> haha, thats true
<FromGitter>
<riffraff169> and global variables are Bad ™️
<FromGitter>
<riffraff169> although classes are global vars....we wont get into that
<FromGitter>
<riffraff169> something has to be global somewhere
<FromGitter>
<oprypin:matrix.org> when i say this, i mean that's actually how they're implemented
<FromGitter>
<naqvis> Thanks @Blacksmoke16 , looks like that's the one
<FromGitter>
<naqvis> but this breaks things
<FromGitter>
<naqvis> like try to use some looping construct inside `Proc`, compiler still insists to use `next` to return from block , imagine what would happen when you do `next` in looping construct :P
<FromGitter>
<Blacksmoke16> :shrug:
<FromGitter>
<naqvis> contrived example https://carc.in/#/r/alkd ⏎ works in previous versions, but no longer works in 1.0
<FromGitter>
<Blacksmoke16> prob should have been marked as breaking i suppose
<FromGitter>
<naqvis> yeah
<FromGitter>
<Blacksmoke16> maybe add a comment to the ticket?
<FromGitter>
<naqvis> thing is, this is not breaking change, but breaks the whole semantics and make using looping constructs inside `Proc` impossible
<FromGitter>
<Blacksmoke16> not exactly
<FromGitter>
<Blacksmoke16> just have to do it differently
<FromGitter>
<naqvis> how would you do it?
<FromGitter>
<Blacksmoke16> well this *would* be possible but there is another bug it seems
<FromGitter>
<riffraff169> i could try that...is there a benefit to using one over the other? my input and output wont be very big, so memory and cpu probably wont be a factor
<FromGitter>
<riffraff169> although the case tuple check will be useful later...i might just keep it in that way as an easy reference
<FromGitter>
<riffraff169> learning something new all the time
<FromGitter>
<riffraff169> how do you guys feel about doing type checking with .is_a? i read an article one that writing code that depends on type checking means your code needs to be rewritten...im not sure i care really, although that is why i was having a type var in it rather than using the class as the type
<FromGitter>
<Blacksmoke16> i think it depends on what you're doing exactly
<FromGitter>
<riffraff169> well, how about in the case where lexeme.value type (String, Int32) doesnt match unless lexeme is the right type, like OpToken instead of StringToken
<FromGitter>
<riffraff169> the case tuple would just not match, whereas the if would fail to compile
<FromGitter>
<Blacksmoke16> why would the `if` fail to compile? I'm pretty sure the case expands to the `if` code i put there
<FromGitter>
<Blacksmoke16> unless a subtype overrides it
<FromGitter>
<riffraff169> ok, so here is where my confusion is/was then
postmodern has quit [Quit: Leaving]
<FromGitter>
<riffraff169> `==`, `===` doesn't fail compilation when types don't match... `=` does though
<FromGitter>
<riffraff169> does return `false` though
<FromGitter>
<Blacksmoke16> you can compare incompatible types, but ofc if you do like `foo : String = 1`, that would fail because you're trying to assign `1` to `foo` which can only be a `String`
<FromGitter>
<riffraff169> great, im clear now
<FromGitter>
<riffraff169> thanks!!!
where_is_x has quit [Read error: Connection reset by peer]
where_is_x has joined #crystal-lang
<FromGitter>
<riffraff169> my code is working now with the token classes...now to add some enums and stuff, then i can start working on the actual parsing
<FromGitter>
<Blacksmoke16> 👍
postmodern has joined #crystal-lang
<FromGitter>
<resuni:matrix.org> What's the best way to determine if a variable was declared nilable? For example, `test_var : String?` vs `test_var : String`.
<FromGitter>
<Blacksmoke16> at runtime?
<FromGitter>
<resuni:matrix.org> No, at build time.
<FromGitter>
<resuni:matrix.org> I don't understand how that would work at run time.
<FromGitter>
<Blacksmoke16> idt you can access local variables in macro land so afaik there wouldnt be a way to do that
<FromGitter>
<Blacksmoke16> unless `test_var` is an instance variable?
<FromGitter>
<resuni:matrix.org> Ah, yes it is. Sorry, should have said that in my example.
<FromGitter>
<Blacksmoke16> then it would be like `ivar.restriction.nilable?`
<FromGitter>
<resuni:matrix.org> Can you link to documentation for that? I can't find anything with the "nilable?" function except in macros.
<FromGitter>
<resuni:matrix.org> Haven't spent the time to figure out macros yet. I think this will work though. Thanks!
<FromGitter>
<Blacksmoke16> what are you wanting to do? actually getting the `ivar` in this case might be the harder part
<FromGitter>
<resuni:matrix.org> I have a class with a set of string properties, only some of which are nilable. I'm using a function outside the class to define those, but there is a possibility it will fail. If it fails, I need the function to return nil if the property I'm defining is nilable. If not nilable, I raise an exception.
<FromGitter>
<resuni:matrix.org> I'm just now realizing that my property isn't even being passed to the parse_entry function, so trying to detect that it's nilable isn't a solution. I think I might just have to pass a boolean to the function indicating if a nil response is acceptable.
<FromGitter>
<Blacksmoke16> although i will ask, whats the reason for using a `Hash` in the first place? seems kidna odd
<FromGitter>
<resuni:matrix.org> Hash was only for the example.
<FromGitter>
<resuni:matrix.org> In real life, it's an XML::Node.
<FromGitter>
<Blacksmoke16> ah gotcha
<FromGitter>
<HertzDevil> 😔
<FromGitter>
<resuni:matrix.org> I'm trying to pull properties that may or may not exist, and I thought Hash would be a simpler example since I can rescue the same KeyError.
<FromGitter>
<HertzDevil> btw `ivar` inside that macro is a `MetaVar`, not `InstanceVar`, so you should always be able to get that type however it is declared
<FromGitter>
<resuni:matrix.org> Does that mean I can use ivar in the parse_entry function without having to pass it there?
<FromGitter>
<HertzDevil> but then you have to pass `@type` there
<FromGitter>
<HertzDevil> oh you can
<FromGitter>
<resuni:matrix.org> Wait, you're right. I do need to pass @type there.
<FromGitter>
<HertzDevil> well even if `@type` appears inside `CommonClass`'s def as long as it is `TestClass` that invokes it `@type` will also be that
<FromGitter>
<resuni:matrix.org> ok, thanks that's a huge help
<FromGitter>
<Blacksmoke16> looks like you just need to upgrade `pg`
<straight-shoota>
Yeah probably
<straight-shoota>
btw. don't use `state: archived` with repos that are considered a mirror of a shard. They shouldn't show up as individual shards at all.
<straight-shoota>
`state: archived` is just for cases where a shard is entirely discontinued, not when it basically just changed names
<straight-shoota>
or location
<FromGitter>
<Blacksmoke16> even in the case of them not being a 1:1 port?
<straight-shoota>
then it shouldn't be a mirror of the other one
<FromGitter>
<Blacksmoke16> ah ok that makes sense
<FromGitter>
<Blacksmoke16> sec
<straight-shoota>
probably...
<straight-shoota>
hm, maybe mirror would work, too
<FromGitter>
<Blacksmoke16> i guess my thinking was that "if you were using this shard, you should migrate to x"
<FromGitter>
<Blacksmoke16> but maybe that should be its own role or something
<straight-shoota>
yeah if assert and crserializer are essentially legacy versions of validator
<FromGitter>
<Blacksmoke16> can think of it like a 1.0 to 2.0 thing
<straight-shoota>
The only functionality of a mirror config is that when a shard uses the mirror repo as dependency, it's attributed as a dependency of the shard with the new repo