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
deavmi has quit [Ping timeout: 244 seconds]
deavmi has joined #crystal-lang
zorp has joined #crystal-lang
f1refly has joined #crystal-lang
f1reflyylmao has quit [Ping timeout: 256 seconds]
zorp has quit [Ping timeout: 256 seconds]
postmodern has joined #crystal-lang
<postmodern> how do you properly handle calling methods on a variable that is Nilable?
<postmodern> p device.buffers[0]
<postmodern> Error: undefined method '[]' for Nil (compile-time type is (V4L2::Buffers | Nil))
<FromGitter> <naqvis> postmodern either use `if var` or go with `try` ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5f225cb6cd7bed0e379dc396]
<postmodern> ah ha
<postmodern> is Indexable(T)#unsafe_fetch allowed to reject the fetch?
<postmodern> Trying to index something that relies on UInt32, so I want to reject when index < 0
<FromGitter> <naqvis> shouldn't the `select` be more suitable for this case?
<FromGitter> <naqvis> aahh sorry, you are talking about `Indexable`
<FromGitter> <naqvis> but doesn't fetch just return the value?
<FromGitter> <naqvis> so ignoring that doesn't work in your case?
<FromGitter> <wyhaines> Interesting how much syntactic overlap Ruby 3's static typing has with Crystal typing: https://developer.squareup.com/blog/the-state-of-ruby-3-typing/
<postmodern> i could return nil, but then that would change the type-signature of the Indexable to Buffer?
<FromGitter> <naqvis> postmodern not sure I follow you, got some example?
<FromGitter> <naqvis> @wyhaines yeah, that look like Crystal :P
<FromGitter> <naqvis> good thing, it will make transition of Rubyists to Crystal more smooth
<postmodern> currently doing `include Indexable(Linux::V4L2Buffer)` and `def unsafe_fetch(index : Int) : Linux::V4L2Buffer`. If I `return nil if index < 0` in unsafe_fetch, then i'd have to change the T type to `Linux::V4L2Buffer?`, which i guess works but i'd rather just not deal with nils somehow
<FromGitter> <naqvis> you shouldn't be returning Nil, instead raising exception when `index < 0`
<FromGitter> <naqvis> `raise IndexError.new if index < 0`
<postmodern> ah ha
<postmodern> what's the proper way to convert an Int to an UInt32, if i've already guarded against negative values?
<FromGitter> <naqvis> `.to_uXX`
<FromGitter> <naqvis> like `32.to_u32`
<postmodern> Error: undefined method 'to_uint32' for Int32, hmm
<postmodern> er right u32
<postmodern> v4l2's API is weird and somehow complex (but surprisingly well documented)
<FromGitter> <naqvis> what are you building?
<postmodern> slowly making progress. can query props and set the format, but still can't query the buffers.
<postmodern> v4l2 crystal bindings. i have all of the C stuff mapped in, now working on writing the classes to wrap around the ioctl functions and deal with the structs
<FromGitter> <naqvis> great 👍
<postmodern> i tried researching other language's v4l2 bindings, but everyone designs them slightly differently
<postmodern> goal is to get direct video frame access to the webcam
<FromGitter> <naqvis> awsome
<postmodern> can then use that to do video effects, hopefully more efficient than ffmpeg
<FromGitter> <naqvis> sounds like a huge endeavor
<postmodern> https://gist.github.com/maxlapshin/1253534 just have to support all of that
<FromGitter> <naqvis> 👍 looking forward to that
<FromGitter> <benphelps> if I have a virtual type that I want to pass to a method, and I know it will be only 1 of the virtual types, can I make the compiler not complain about overloading the method to accept the other virtual types?
<FromGitter> <naqvis> got some example?
<FromGitter> <benphelps> sort of psudo code but it gets the gist of it
<FromGitter> <benphelps> statements = [] of Statement ⏎ LetStatement < Statement ⏎ ReturnStatement < Statement ⏎ def check_statement(statements[0] : LetStatement) [https://gitter.im/crystal-lang/crystal?at=5f226692bc41f3681733a82c]
<FromGitter> <naqvis> then use `Statement` as the param
<FromGitter> <naqvis> `def check_statement(statement : Statement)`
<FromGitter> <naqvis> `check_statement(ReturnStatement.new)`
<FromGitter> <benphelps> when I do that, the code in the block expects to handle both Let and Return, but it's only ever Let
<FromGitter> <naqvis> isn't that your intention? or you want method to only handle specific child of Statement?
<FromGitter> <naqvis> if you want method to handle concrete type, then set that as the param type
<FromGitter> <benphelps> exactly, a method per child
<FromGitter> <naqvis> what do you mean by a method per child?
<FromGitter> <benphelps> 1 method to handle each child of Statement
<FromGitter> <benphelps> because they take different arguments
<FromGitter> <benphelps> so I can't overload the same method
<FromGitter> <naqvis> if this is the case, then inheritance doesn't sound a right approach to me
<FromGitter> <benphelps> In spec/parser_spec.cr:32:7 ⏎ ⏎ 32 | test_statement(program.statements[i], expected_identifier) ⏎ ⏎ ``` ^-------------``` ... [https://gitter.im/crystal-lang/crystal?at=5f2267e2cd7bed0e379de006]
<FromGitter> <benphelps> program.statements = [] of AST::Statement ⏎ but in this case, I know that it's only AST::LetStatement
<FromGitter> <naqvis> and what is signature of `test_statement`?
<FromGitter> <benphelps> test_statement(statement : AST::LetStatement, name : String)
<FromGitter> <naqvis> so you are restricting this method to just handle LetStatement?
<FromGitter> <benphelps> yes
<FromGitter> <naqvis> if you know that array is only containing the LetStatement then you can do a casting
<FromGitter> <naqvis> `test_statement(program.statements[i].as(LetStatement), expected_identifier)`
<FromGitter> <naqvis> but this is dangerous and should do this casting, if you know what you are doing
<FromGitter> <naqvis> or else you will get run time exception
<FromGitter> <benphelps> yeah, and it's in a spec so, doubly dubious
<FromGitter> <naqvis> sure
<FromGitter> <benphelps> the type system is beautifully annoying sometimes
<FromGitter> <naqvis> downcasting is causing that
<FromGitter> <benphelps> i do understand why it's complaining, it's just making this test helper harder to write
<FromGitter> <naqvis> because compiler can't know if there won't be any other sub-class of Statement in that array
<FromGitter> <naqvis> and it does make sense to be explicit
<FromGitter> <benphelps> yeah, exactly
<FromGitter> <benphelps> i can't overload and have different arguments, right?
<FromGitter> <naqvis> you can
<FromGitter> <benphelps> eventually, I do need a method to handle each child type, it's just the arguments are different
<FromGitter> <benphelps> so its right in complaining about missing overloads
<FromGitter> <benphelps> i just haven't made it that far
<FromGitter> <benphelps> yeah, no, it comes back to the first method
<FromGitter> <benphelps> Error: no overload matches 'test_statement' with types AST::Statement+, String ⏎ ⏎ Overloads are: ⏎ ⏎ 1) test_statement(statement : AST::LetStatement, name : String) ... [https://gitter.im/crystal-lang/crystal?at=5f226a4477eccd0e14846234]
<FromGitter> <naqvis> Order matters
<FromGitter> <benphelps> Error: no overload matches 'test_statement' with types AST::Statement+, String ⏎ ⏎ Overloads are: ⏎ ⏎ 1) test_statement(statement : AST::LetStatement, name : String) ... [https://gitter.im/crystal-lang/crystal?at=5f226afdfe6ecd2888827b7a]
<FromGitter> <benphelps> because I call test_statement with a string in the test where I know it's only LetStatement, it expects an overload for the other types
<FromGitter> <benphelps> maybe casting is the only way ?
<FromGitter> <naqvis> no
<FromGitter> <naqvis> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5f226b79a050df43002485fb]
<FromGitter> <naqvis> this is the root cause
<FromGitter> <naqvis> concrete methods of `ReturnStatement` you have doesn't have overload which contains `String`
<FromGitter> <naqvis> why not mark that `String` argument with default value?
<FromGitter> <naqvis> so you know when arg is default, this is something else
<FromGitter> <benphelps> if I call it like this ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ it works fine [https://gitter.im/crystal-lang/crystal?at=5f226c37c1c0090e64affff3]
<FromGitter> <naqvis> take a look at `call` overloads, and i'm also mimicking passing items from Array of Statement
<FromGitter> <benphelps> it's just the argument here that's breaking it down
<FromGitter> <naqvis> so only LetStatement has `expected_identifier`?
<FromGitter> <naqvis> while others won't?
<FromGitter> <benphelps> yeah
<FromGitter> <naqvis> then make `test_statement` as ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5f226d32fe6ecd28888282ac]
<FromGitter> <naqvis> make last argument default
<FromGitter> <benphelps> yeah, that's probably my cleanest option
<FromGitter> <benphelps> casting does work but I don't like that, forcing the type to be know using is_a? works but that adds a lot of code
<FromGitter> <naqvis> yes
<FromGitter> <naqvis> but you already have overloaded methods for different sub-classes
<FromGitter> <naqvis> then you needn't to do casting
<FromGitter> <naqvis> looked at my example above
<FromGitter> <naqvis> https://play.crystal-lang.org/#/r/9gy9 no casting is required
<FromGitter> <benphelps> yeah, casting just forces the singular type rule thingy, I'm guessing the same as is_a?
<FromGitter> <benphelps> cool, thank you for the help :)
<FromGitter> <naqvis> 👍
<postmodern> with c bindings, what's the proper way to represent an opaque struct type?
<FromGitter> <naqvis> `Pointer`?
<postmodern> `alias FooPtr = Pointer`?
<FromGitter> <naqvis> yeah
<FromGitter> <naqvis> `alias FooPtr = Void*`
<FromGitter> <benphelps> Finished in 3.74 milliseconds ⏎ 102 examples, 0 failures, 0 errors, 0 pending ⏎ Thanks again Ali
<FromGitter> <naqvis> great, you are welcome Ben
<postmodern> any thoughts on how to port this to crystal? Crystal's Proc.new is different from Rubies. https://github.com/postmodern/ffi-extractor/blob/master/lib/ffi/extractor/metadata_processor.rb#L59
<postmodern> basically just needed to wrap a proc that's passed to a C function as a callback and do map the data and handle a throw/catch
<FromGitter> <benphelps> can I have a hash of closures?
<FromGitter> <j8r> yes, a hash of procs
<FromGitter> <benphelps> can I alias a closure type ?
<FromGitter> <benphelps> Proc, I guess
<postmodern> alias MyClosure = (...) -> ...
<FromGitter> <benphelps> I'm following a book on writing a programming language parser, it's for the Go language, implementing it in Crystal
<FromGitter> <benphelps> ```code paste, see link``` ⏎ ⏎ alias InfixParser = Proc(AST::Expression, AST::Expression) ⏎ ⏎ prefix_parsers = {} of Token::Type, PrefixParser ... [https://gitter.im/crystal-lang/crystal?at=5f227fd4e9066820052873ca]
<FromGitter> <benphelps> I'm guessing that all makes sense ?
<FromGitter> <benphelps> methods can't be assigned to a variable like JavaScript or Go, so I have to use Proc's, if I'm going to follow the structure of this books examples
<FromGitter> <benphelps> at least from what I understand reading through the crystal gitbook
<FromGitter> <benphelps> ahh, seems to not complain at least after fixing the syntax
<FromGitter> <naqvis> @benphelps `{} of KeyType => ValueType`
<FromGitter> <naqvis> not comma
<FromGitter> <naqvis> `prefix_parsers = {} of Token::Type => PrefixParser`
<FromGitter> <benphelps> yeah, but that gives an interesting error from the compiler
<FromGitter> <benphelps> expected -> not NEWLINE
<FromGitter> <benphelps> but I figured it out :P
<FromGitter> <naqvis> :P
<FromGitter> <benphelps> would you say it makes more sense to alias types in a Module over a Class
<FromGitter> <benphelps> even if it's only going to be used in this one class
<FromGitter> <naqvis> alias usage is different, not sure I understand your point here
<FromGitter> <benphelps> maybe I'm trying to match the structure of the Go implementation too closely
<FromGitter> <benphelps> but he defines a function (template?, type?) with specific arguments and return values, the closest I can get in Crystal is a Proc alias
<FromGitter> <naqvis> in Go func pointers are good to be translated as alias
<FromGitter> <naqvis> the way you have done above
<FromGitter> <naqvis> that seems good
<FromGitter> <benphelps> alright, I'll roll with it and see where it falls apart, haha
<FromGitter> <naqvis> 👍
<FromGitter> <benphelps> are these the same? ⏎ ⏎ ```alias PrefixParser = -> AST::Expression ⏎ alias PrefixParser = Proc(AST::Expression)``` [https://gitter.im/crystal-lang/crystal?at=5f2282edfe6ecd288882c50a]
<FromGitter> <naqvis> yeah
<FromGitter> <naqvis> `->` is just a shorthand syntax for `Proc`
<FromGitter> <naqvis> postmodern https://crystal-lang.org/reference/syntax_and_semantics/c_bindings/callbacks.html would suggest to go through reference guide
<FromGitter> <benphelps> oh man this is so annoying
<FromGitter> <benphelps> ```code paste, see link``` ⏎ ⏎ because of my virtual types [https://gitter.im/crystal-lang/crystal?at=5f228f4127799668010f12a8]
<FromGitter> <benphelps> AST::LetStatement doesn't have an expression property, AST::ExpressionStatement does
<FromGitter> <benphelps> trying to test the expression property on an AST::ExpressionStatement and it's complaining because AST::LetStatement wouldn't have that property
<FromGitter> <benphelps> I'm inside a `if statement.is_a?(AST::ExpressionStatement)` block, so the type is guaranteed to be an AST::ExpressionStatement, but it still complains
<FromGitter> <dorianmariefr> is there any way to have some sort of "did_you_mean" but for crystal?
heidar has quit [Ping timeout: 244 seconds]
<jhass> the compiler already does that in some cases
<jhass> >> foo = 1; fo
<DeBot> jhass: Did you mean 'foo'? - https://carc.in/#/r/9gzf
_whitelogger has joined #crystal-lang
Elouin has quit [Ping timeout: 246 seconds]
<postmodern> wait so crystal lacks throw/catch?
<postmodern> should i raise an exception instead to perform a long-jump back to the catch point?
<Rounin> postmodern: I mean, raise is the same as throw, though, isn't it?
<Rounin> and rescue is the same as catch
<Rounin> I'm not sure I would say exceptions are the ideal thing for control flow in a program, but it's certainly a simple way to jumpt out of some nested code
<Rounin> If you do it often, I would expect that it eats some CPU time
<Rounin> I wonder what happens in C, if you make a label "gohere:" and then goto gohere from a function many levels down from that label... Does it neatly unwind all the stack frames, or just jump and leave everything a mess
<postmodern> Rounin, i mean sure you can emulate throw/catch usig exceptions and even embed any additional variables into the exception object
<postmodern> Rounin, in C goto's are function local, to long-jump back several functions, you have to use setjmp() and longjmp()
<Rounin> postmodern: Oh, OK... Regarding throw/catch, though, in Java, those are used for exceptions... throw/catch and exceptions are one and the same
<Rounin> I'm not familiar with any other use
<postmodern> Rounin, ah in Ruby throw/catch behave like raise/rescue, but can pass data back to the catch()ing block
<Rounin> postmodern: Oh, so ... It's kind of an extra exception mechanism, which is slightly different? I've been using Ruby for years, and I had no idea
<Rounin> That's very interesting... You learn something new every day
<Rounin> From reading up on it for like 2 seconds, I guess what you throw with throw isn't typically an exception, so it's more general?
<Rounin> In which case, that's very clever... Perhaps other languages could benefit from that flexibility
<postmodern> yeah i used it in this ruby library to wrap around a passed in block. If the block happens to call Extractor.abort! it throws an :abort signal. In the outer wrapping block around the user given closure, i catch the :throw and return 0, indicating to the C function that the callback wants to break out of the loop it's running
<postmodern> this way the user given closure doesn't have to worry about explicitly returing 0 or 1, since that's a C thing that we're trying to abstract away
Elouin has joined #crystal-lang
<Rounin> Ah... Interesting mechanism, that... Very interesting
sorcus has quit [Quit: WeeChat 2.9]
sorcus has joined #crystal-lang
<postmodern> hmm trying to append *arguments from a closure to an [] of Tupes, but I'm getting this error:
<postmodern> Error: no overload matches 'Array(Tuple(Symbol, LibExtractor::MetaType, LibExtractor::MetaFormat, String, Slice(UInt8) | String))#<<' with type Symbol
<FromGitter> <Blacksmoke16> Looks like you're trying to push a symbol, not a tuple?
<postmodern> i double checked that the arguments passed to the proc matches the tuple
<postmodern> `findings << arguments`
<postmodern> this is within a spectator spec, so macros might be doing something weird...
<FromGitter> <Blacksmoke16> :shrug:
<postmodern> explicitly specifying the closure arguments and crafting a tuple with them worked, :shrug: indeed
<postmodern> hmm how to convert a Pointer(Char) to a String? All of the String constructors take Pointer(UInt8)
<postmodern> ah tht was a Char vs LibC::Char issue
<postmodern> hmm you can't use yield within proc literals? :(
<postmodern> guess i'll turn that into a class
<postmodern> hmm why doesn't ->call work from within an instance method, but ->obj.call works outside of the class?
<FromGitter> <Blacksmoke16> hm?
<postmodern> ah i have to do ->call(ArgType1, ArgType2, ...)
<postmodern> hmm now cutting my teeth on parsin YAML
<postmodern> trying to parse the YAML arrays, coerce via #as_a, then convert that to Tuples via MyTuple.from(array)
<FromGitter> <Blacksmoke16> prob have to cast each item in the array as something as well
<FromGitter> <Blacksmoke16> otherwise you end up with `Array(YAML::Any)`
<FromGitter> <Blacksmoke16> or maybe use serializable stuff
<postmodern> is there an easy to convert Strings to Symbols?
<FromGitter> <Blacksmoke16> no, but you can do the otherway around
<postmodern> (the yaml contains symbols that are supposed to map to some enums)
<FromGitter> <Blacksmoke16> prob could use a converter to pass the string/symbol to `.parse` of the enum
<postmodern> like MyEnum.parse(array[1].as_s) ?
<postmodern> not sure how crystal's YAML implementation will handle ":sym"
<FromGitter> <j8r> how can bcrypt be useful...
<FromGitter> <Blacksmoke16> no i mean a custom converter
<FromGitter> <Blacksmoke16> where you interact directly with `YAML::PullParser`
<FromGitter> <j8r> I would like to create a `Crypto::Bcrypt` from a digest: https://github.com/crystal-lang/crystal/blob/master/src/crypto/bcrypt.cr
<FromGitter> <j8r> I would like to know if a given password match the digest I have
<postmodern> j8r, i believe you calculte the bcrypt hash from the password, then compare the resulting digest with what you have on file
<FromGitter> <j8r> I think I got the thing
<FromGitter> <j8r> yeah, I do `Crypto::Bcrypt.new` for each try
<FromGitter> <j8r> btw, `Crypto::Bcrypt.hash_secret` is useless lol
<FromGitter> <j8r> I mean, it could have been `salt : String = Random::Secure.random_bytes(SALT_SIZE)` in the `.new`
HumanGeek has joined #crystal-lang
Human_G33k has quit [Ping timeout: 256 seconds]
<FromGitter> <j8r> ...I was not expected the stdlib to have such thing...
<postmodern> is there a way to define additional methods on a type-alias?
<FromGitter> <Blacksmoke16> hm?
<FromGitter> <Blacksmoke16> would have to define them on the aliased type
<FromGitter> <Blacksmoke16> if i follow your thinking
<postmodern> like if I defined `alias MetaData = String | Slice(UInt8)`, could I add custom .from or .parse methods to handle coercion?
<FromGitter> <Blacksmoke16> they would have to be defined on `String` and `Slice`
<FromGitter> <Blacksmoke16> aliases dont really exist at runtime, as they get replaced with their definition
<FromGitter> <j8r> yep, you need then `.is_a?` stuff
<FromGitter> <j8r> or, you can also use a struct instead of an alias called `MetaData`, and do the `is_a?` logic inside
<FromGitter> <j8r> (or `case/when`)
<FromGitter> <j8r> and have a `#raw` to access the underlying value. That's what `JSON::Any` does
heidar has joined #crystal-lang
<postmodern> what is the preferred way to convert a Char * c-string into a String?
zorp has joined #crystal-lang
<postmodern> nm, LibC::Char is aliased to UInt8
<postmodern> hmm that's odd String.new doesn't check for Pointer#null?
postmodern has quit [Quit: Leaving]
<FromGitter> <ImAHopelessDev_gitlab> ME: https://i.imgur.com/iY8MD06.mp4 😂😂
deavmi has quit [Quit: No Ping reply in 180 seconds.]
deavmi has joined #crystal-lang
<FromGitter> <wontruefree> hahaha nice
duane has quit [Ping timeout: 264 seconds]
sagax has joined #crystal-lang
<FromGitter> <plainas> asd
heidar has quit [Ping timeout: 240 seconds]
Munto has quit [Quit: Leaving]
<FromGitter> <benphelps> can I get the API docs offline?
<FromGitter> <benphelps> i have the reference offline but not the API docs
<FromGitter> <Blacksmoke16> https://github.com/crystal-lang/crystal/releases/download/0.35.1/crystal-0.35.1-docs.tar.gz can download them from a release
<FromGitter> <benphelps> oh awesome, thank you
<FromGitter> <j8r> one other option is clone the repo, then `crystal docs`
<FromGitter> <Blacksmoke16> `make docs`
<FromGitter> <j8r> an other option too, but requires build stuff
<FromGitter> <benphelps> cool, long train ride tomorrow and no internet, gonna need these
<FromGitter> <benphelps> thanks guys
<FromGitter> <j8r> hum I guess it can't work properly out of the box :(
<FromGitter> <Blacksmoke16> ye
<FromGitter> <j8r> ... Someone has an idea why `Crypto::Bcrypt::Password` is not in `Crypto::Bcrypt`?
<FromGitter> <j8r> I'll ask to the forum, I spotted some API inconsistencies in
coderobe has quit [Quit: Ping timeout (120 seconds)]
coderobe has joined #crystal-lang
_whitelogger has joined #crystal-lang
Vexatos has quit [Quit: ZNC Quit]
Stephie has quit [Quit: Fuck this shit, I'm out!]
rocx has joined #crystal-lang
Vexatos has joined #crystal-lang
Stephie has joined #crystal-lang