<FromGitter>
<sdogruyol> Great thanks @bararchy how about you?
Raimondii has joined #crystal-lang
Raimondi has quit [Ping timeout: 268 seconds]
Raimondii is now known as Raimondi
<FromGitter>
<codenoid> i'ts natural barachy
<FromGitter>
<codenoid> N A T U R A L ✨
<FromGitter>
<codenoid> i just adding a "btw sorry for all those "little mistakes" and typos" to the desc 😆
<hightower>
Hey, I have a string with say, 3 chars: 0x1A, 0x1 and 0x1C. My first question is can I index it using str[0], str[1] and str[2] for individual chars, as I normally would. The second question is what do I need to run on an individual char, to get it suitable for executing (char)<<8 on it? I tried char.to_i << 8 but it gave me "Invalid integer"
<oprypin>
hightower, what, you too? storing bytes in a string?
<hightower>
oprypin, reading a compiled terminfo file
jihantoro has joined #crystal-lang
<FromGitter>
<bararchy> XD
<oprypin>
hightower, you say "0x1A" which is clearly a number and call it a char and put it in a string? wut
<oprypin>
you are supposed to read with slices of bytes
Ven has joined #crystal-lang
Ven is now known as Guest11421
<jihantoro>
buffer input
<hightower>
oprypin, I do data= File.read( file), and after that it looks like I can properly access "chars" by doing data[1] etc. What specifically do you suggest instead? That I operate on data.bytes?
<oprypin>
hightower, I suggest that you do not read a file that does not consist of text into a type which can only hold text
<oprypin>
the proper way is reading into a slice (gotta check how that's done, hold on)
<FromGitter>
<straight-shoota> If you are certain, `a["two"]` will always be of type `Hash` you can cast it to Hash: ``` ⏎ a_test = a["two"].as(Hash(String, Bool) ⏎ a_test["two"] = true
<hightower>
Got it, thanks. Right, done so, but it is unclear to me why this isn't working by default
<FromGitter>
<codenoid> pwned why ? , you need bridge to get through the ocean
<hightower>
My code is really straightforward I would say, let me prepare a snippet
<oprypin>
hightower, what is not working by default? i'd say the compile time safety is working pretty damn well
<oprypin>
you can always turn that into a runtime error instead with `as` but it's good to acknowledge you're doing it
<hightower>
What is surprising to me is that I do code like: x = {} of String => Bool | Hash(String, Bool_. Then I do x["y"]= {} of String => Bool. And then I want to do x["y"]["z"]= true, and that doesn't work unless I add as() as you advised.
<hightower>
The as() is intrusive, especially since it was specifically already said that x["y"] is Hash(String, Bool)
<oprypin>
come on...
<oprypin>
what if i implement a data structure in which after every addition it reshuffles the values among keys
<oprypin>
Then I do x["y"]= {} of String => Bool. And then I want to do x["y"]["z"]= true and whoops it's not actually a Hash anymore cuz the value has been reassigned immediately
<jihantoro>
is x can be x["y"]["stringkey"] = bool value ?
<jihantoro>
o
<jihantoro>
an how to automatically set int type
<jihantoro>
i mean, when i use BIGINT for my table and set type data as Int32, Crystal says, IS A WRONG DATA TYPE, YOU MUST BE SET TO Int64, ,, me : why you dont automatically change it
<Groogy>
does values in Crystal automatically initialize to like zero?
<Groogy>
you can also ask what is the initial value for specific members
jihantoro has quit [Quit: Leaving]
<FromGitter>
<straight-shoota> Yeah but that's not possible in general, because some types have no default value without any external initialization parameter and would be in an invalid state if it was not initialized properly.
<crystal-gh>
[crystal] RX14 opened pull request #4718: Add specs for debug info output (master...debug/spec-with-gdb) https://git.io/vQFWz
<FromGitter>
<straight-shoota> Does anyone know a thing or two about linking custom libraries into crystal? I'm trying to us a local build of libsass in travis-ci without sudo. So far, I've managed to get it running, but cannot use `crystal spec` directly, because there seems no way to specify a custom library directory. I have to run `crystal build` (with `--link-flags -L$LOCAL_LD_PATH}` for the spec_file(s) and execute the
<Groogy>
Kind of, I am just trying to reduce code duplication so I don't have to implement the same thing for 2, 3 and 4
<Groogy>
on SIZE
<Groogy>
if you have a better idea tht is more Crystal that could work as well
<oprypin>
Groogy, sounds like the use case for an array??
<Groogy>
nah it's a mathematical vector, array has overhead right since it isn't allocated on the stack? Since it's gonna be used everywhere for intense math operations need to consider that
<oprypin>
that's a mess you've got there with travis commits. i'd do it in a branch or force push it all away
rohitpaulk has joined #crystal-lang
<FromGitter>
<straight-shoota> @oprypin I wanted to call `crystal spec` directly instead of building first and then executing the binary manually.
<FromGitter>
<straight-shoota> providing `LIBRARY_PATH` to `crystal spec` helps, that's what I was looking for :D Did only find `--link-flags -L/path/to/lib` which is only available on `crystal build`
<FromGitter>
<straight-shoota> Thanks!
<FromGitter>
<straight-shoota> I'll clean up the commit history. You're right, I should've done it in a branch in the first place :/
rohitpaulk has quit [Ping timeout: 246 seconds]
<FromGitter>
<muhajirframe> Hi guys, I found this lang like a few days ago. I have a JS background. And I see people are transitioning to golang from nodejs. Some thought on this maybe? Or any JS guy coming to crystal lang?
rohitpaulk has joined #crystal-lang
<Groogy>
hmm if you map a static array, it becomes a non-static array
<Papierkorb>
muhajirframe, Just give Crystal a try. If you ever used Ruby, you'll feel right at home, if not, you'll see some new concepts. If you need a language that is production-ready™ right now, use awful Go-lang. In any case, give it a whirl and build something small, shouldn't take more than a few hours, and you know more
<Groogy>
is there a way to pass an operator as argument to a macro? I get unterminated call when trying :/
<Papierkorb>
muhajirframe, language-wise, you can't really compare Go and Crystal. TL;DR: Go wants to impress by being unimpressive, Crystal wants to impress by being the next-Ruby-ish, continuing what made Ruby great, and somewhat improving what made Ruby suck.
<Papierkorb>
Groogy: Operators are methods: `1.+(2) == 1 + 2`, so the syntax is `.+`
<Groogy>
on SIZEyeah it doesn't like it though :/
<Papierkorb>
You'll have to share some code showing the issue then
<Papierkorb>
Groogy: w.r.t. to your code, you should use a method instead, which yields. E.g.: `def +(..); self.class.new(do_math{|a, b| a + b}; end`
<Groogy>
yeah I know
jihantoro has joined #crystal-lang
<Papierkorb>
That won't be any slower, but easier to test and lesser likely to blow up unexpectedly
<jihantoro>
hi groogy, what the mean of private macro
<Groogy>
just that only this class can internally use it?
<Groogy>
Papierkorb will LLVM unwind the loop then?
<Papierkorb>
Groogy: If you use it in a macro? It's unwinded right then and there, LLVM never sees any macro stuff
<Groogy>
no I meant the yield
<Groogy>
or is that a macro as well?
<Groogy>
I mean inside the do_amth there would still be the @ellements.each { ... }
<Groogy>
do_math*
<Papierkorb>
Well if you yield, the block will be inlined into the called method, effectively creating a whole new method. A while-loop or #each of any sort is then again up to LLVM to do something about it - Or not
<Groogy>
hmm
<Papierkorb>
If you stick to the macro version, I'd still use {% for k in 1..times %} instead of recursion
<Groogy>
I could also just specialize the counts of 2, 3 and 4 and let it do a loop for any bigger sizes
<Groogy>
which would be in itself more code but maybe look prettier?
<Papierkorb>
code duplication is never pretty
<Papierkorb>
Use a macro if you have to for such cases, a macro is still more maintainable than manually writing whatever multiple invocations of that macro would've produced
<Groogy>
yeah alright
hightower has quit [Ping timeout: 255 seconds]
<Groogy>
hmm for some reason it doesn't evaluate to a number literal? which is weird
<Papierkorb>
`it`?
<Groogy>
"range end times must evaluate to a NumberLiteral" for my number literal SIZE
<Papierkorb>
durr
<Groogy>
I'll just do it a method and hope LLVM can see that it can unwind the array
<Groogy>
unwind the loop*
<Papierkorb>
Benchmark it
<Papierkorb>
Write both, manually unrolled and loop version, and benchmark that
<Groogy>
will do
<Papierkorb>
Use the "benchmark" stuff if you haven't before
<Papierkorb>
With those runtimes, noise alone can reverse such a small difference on the next run easily. I wouldn't bother and just use the loop variant
<Groogy>
yeah it kind of tells me that LLVM is unwinding the loop
<Papierkorb>
it may or may not. you can check in the disassembly of course, but eh
<Groogy>
though just to seee so there is no overhead I am missing making the test unfair I'll paste the test
<Groogy>
even in debug the difference is just like 1.17x times
rohitpaulk has quit [Ping timeout: 248 seconds]
<Groogy>
and yeah now in release I got unrolled is slower by basically nothing. So pretty sure LLVM is smart enough to see that this static array loop will never change size and just unrolls it
<Papierkorb>
Looks fine to me. If you wanted to go faster, you'd have to use platform specific assembler for e.g. SSE - if LLVM isn't smart enough to just do that
<Groogy>
nah it's not that critical in speed :P so this should be good enough
rohitpaulk has joined #crystal-lang
<Papierkorb>
Oh yeah, you're using static arrays, I forgot. In that case it really should be smart enough to do that
<Groogy>
but this was a good experiment to know for the future ^^
<Groogy>
for let's say vertex processing etc.
Nouv has joined #crystal-lang
<Papierkorb>
Yeah, tbh, Crystal code is generally faster than it has any right to be.
<Papierkorb>
Though 99.9% on that is LLVM
Nouv has quit [Read error: Connection reset by peer]
Nouv_ has joined #crystal-lang
Nouv_ has quit [Client Quit]
<Groogy>
though you don't need to write a += operator right?
<Groogy>
it does the magic for you like in Ruby?=
<Papierkorb>
`+=` is defined as `a += b` -> `a = a + b`
<Papierkorb>
same for the other do-something-and-assign operators
<Groogy>
yeah
<Groogy>
heh I still ended up using macros though differently
<Groogy>
def_vector_math(:+)
<Groogy>
which creates the method since it's gonna be the same for every operator
<Groogy>
But this is great, thanks Papierkorb and oprypin! Now I don't have to duplicate the code depending on amount of elements :)
<Groogy>
hmm can I do an argument type that matches any variant of a generic type?
<Groogy>
like any sorts of array?
<Groogy>
but it is specific for only arrays
<Papierkorb>
Enumerable or Iterable are good candidates
<Groogy>
no I mean Specifically Array(T) but not Array(Int32)
<Groogy>
var : Array(T) is that valid?
<Papierkorb>
if T is defined, yes
<Papierkorb>
through a generic
<Groogy>
hmm :/ I just want to define a Math.some_math_operation_like_dot_product function that would work against any type
<Groogy>
for my vectors
<Papierkorb>
You shouldn't add your own methods to the global Math module.
<Groogy>
though I could just omit the type completly
<Papierkorb>
Either that, or this: `do stuff(list : Enumerable(T)) forall T`
<Papierkorb>
Restricting it to Array isn't great if you have no reason for requiring an array
<Groogy>
no it's for vector was just using array as example
<Papierkorb>
Why not have a Vector#dot_product then?
<oprypin>
Groogy, you literally just restrict : Array
<oprypin>
and when you need the T somewhere, you do what Papierkorb wrote forall
<oprypin>
man i hate that syntax though
<Yxhuvud>
agreed. It is action at a distance.
rohitpaulk has quit [Ping timeout: 260 seconds]
rohitpaulk has joined #crystal-lang
<Groogy>
hmm it's not possible to use constants as arguments for a generic? Also you can't do Size * Size (if Size is a generic argument) as an argument for another generic?
<Groogy>
and right now I am just trying to figure out how to create a generic way to create an identity constant
<FromGitter>
<straight-shoota> this is nice :)
<Groogy>
THere is Type.zero but not Type.one :P
<FromGitter>
<straight-shoota> what Type.zero?
<Groogy>
eh replace Type with Int32, Float64, etc. etc.
<Groogy>
class method that returns 0
<Papierkorb>
Groogy: `Type.new(1)`
<Groogy>
that will work with any type?
<Papierkorb>
Any type? nah. numerics? yep
<Groogy>
ah yeah numerics is what I mean
<Groogy>
I thought it would be cranky because it is an int literal and not a float literal for a float type etc.
<Groogy>
but that's good
<Groogy>
ow yeah, so if I define a IDENTITY matrix constant, I know it's called constant but is it constant as in Ruby sense or in C++ sense?
<Groogy>
As in can the data in it actually change or is it just the constant can't be reassigned?
<Papierkorb>
The reference is constant, the value can be mutable
<Papierkorb>
Well, if you can, make it immutable
<Groogy>
dang :/ alright so then I will have to have the structures never allow modifying themselves, which is fine in this case but good to know for future
<Groogy>
though does mean you can use hte []= operator which would be a problem, might throw in an exception there
<Groogy>
raise Exception.new if pointerof(self) == IDENTITY
<Groogy>
or some such
<Groogy>
oh yeah if pointer of identity is same of course
<Papierkorb>
You can enforce it by either having a read_only flag (I don't really like that solution though), or by using OOP: Vector < ReadOnlyVector
<Papierkorb>
So that a Vector can be downcasted to a ROVector, but not the other way around
<Groogy>
and the Vector class would only be implementing the setter functions
<Groogy>
yeah that's kind of nice
<Papierkorb>
I did request a `const` long time ago, but people didn't like it. Also liked const in C++ ...
<Groogy>
and with structs that don't allow virtual it should be pretty efficent still?
<Papierkorb>
you can inherit from an abstract Struct, but you can't inherit from a non-abstract one. So, `struct` won't really work for you here I guess
<Groogy>
hmm
<oprypin>
just use structs, who cares about mutability
<Papierkorb>
Good APIs do
<Groogy>
I do, because if you accidentally modify the IDENTITY matrix in your lib you're gonna have a bad time finding where the error originates from
<Papierkorb>
People were yelling at me when I wanted to turn an Array into a Slice because mutability. People can't yell when I advise an API which is inmutable.
<Groogy>
since that is gonna cascade throughout your hiearchy
<oprypin>
structs are copied by value
<oprypin>
but sure, make matrix a class maybe
<Papierkorb>
`IDENTITY[1, 2] = 5` won't be "copied"
<Groogy>
yeah but all you need to do is IDENTITY.some_op(other)
<Groogy>
and you might be fucked
<Groogy>
since you can't mark methods as "I do not change my internal values" either
<Groogy>
that mistake can very easily happen
<Papierkorb>
Groogy: in any case, for large-ish vectors, constantly copying the structure become a performance penality.
<Groogy>
Well yeah but it's gonna be fine for linear algebra for doing 3D
<Groogy>
where largest vector is gonna be 4x4
<Papierkorb>
And sometimes you *do* want to pass in a "mutable reference"
<Groogy>
i.e a matrix
<Groogy>
or well I mean vectors are 1x* matrices but you get what I mean
<Groogy>
problem with makign it a class is you gonna have tons of poltergeist-style objects for no reason
<Groogy>
which is going to have it's own overhead
<Papierkorb>
Mh I just wondered how big the backslash would be when someone would request a pass-by-reference syntax, like `def foo(bar : &SomeStruct)`
<Groogy>
well there isn't really a reason in this language to have that since you can return multiple values?
<Groogy>
I mean sure that is more efficent but.... :shrug:
<Groogy>
if the objects behave more like numbers and you are force to treat them like that I think it is less likely you do mistakes with them?
<Papierkorb>
*values
<Papierkorb>
and well, that wouldn't change
rohitpaulk has quit [Ping timeout: 260 seconds]
<oprypin>
Papierkorb, you can do this if you really want to with pointerof
<oprypin>
backlash would be pretty damn big lol
<oprypin>
structs were almost made immutable at one point
<Groogy>
Yeah I would just say if you need that kind of behaviour you have plenty of other ways to solve it
<Groogy>
the &SomeStruct is very much C/C++
<oprypin>
and honestly making them immutable wouldn't even be all that bad
<oprypin>
making me also believe that pass by reference syntax has little use
<Groogy>
actually every single method in the vector pretty much creates a new one with self.class.new { |index| do stuff }
<Groogy>
so I would survive with it
<Papierkorb>
oprypin: of course you can do it with pointerof. Heck, I even have ValueRef for this.
<oprypin>
uhh
<Papierkorb>
but i wouldn't even request it at this point even if I actually wanted it.
<oprypin>
at this point I believe that it has to be a really extreme case for structs to give noticeable performance advantage over references
rohitpaulk has joined #crystal-lang
<Groogy>
i.e boiler plate code
<Groogy>
hmm why does it say that this constant doesn't exist? Definition of it is IDENTITY = self.new()
<Groogy>
does aliases prevent accessing constants or something such?
<oprypin>
Groogy, doesnt sound like an error that should happen. example pls.
<Groogy>
but yeah it works and is good enough, since it is just semantic sugar really
<Groogy>
and since it is on the stack and just simply number operations, if you do something unnessecary and dumb the compiler should have enough info available to optimize it away
<Groogy>
both should net the same result, even same assembly since Value#dup just returns self but I am curious what is more "this is how you should do it in crystal"
pwned has quit [Ping timeout: 260 seconds]
<Papierkorb>
Groogy: Both are fine, though the former is more robust. Maybe #clone is better than #dup semantic-wise, but in your case, both are the same
<Papierkorb>
Groogy: #dup is meant to create a shallow copy, #clone is the deep-copy pendant
<Groogy>
and #clone for a struct/static array I am guessing is going to be pretty much the same thing?
<Groogy>
except that clone might go through the static array to find objects to copy?
<Papierkorb>
For value types. Struct and StaticArrays are value types, and in your case, these only contain other value types, so they're the same
<Papierkorb>
that's done at compile time. LLVM should optimize those useless calls away.
<Groogy>
I usually forbid any kind of modification of arguments at work with c++ because as code base grow it increases chance of someone fucking up. So probably gonna retain the same attitude in Crystal then
<Groogy>
since the compiler is gonna be super smart about it anyway
<Papierkorb>
The downside of "always use #clone" is that #clone isn't implemented by default. #dup isn't either, but duplicating the container won't duplicate its (possibly) non-dup/clone-able child objects, so it's a non-issue there
<Groogy>
also you said before do not add stuff to the Math module, though I have put stuff like vector X vector outside of the struct since it needs to only be valid for Vector of size 3, you find adding a Math.cross() is a nono?
<Groogy>
and in that case why?
<Papierkorb>
Because you're messing with a module you don't own, and should be kept to a minimum.
<Papierkorb>
Solutions could be `Vector.cross` (which makes it really obvious what it's doing), or `YourVectorLib.cross`
<Papierkorb>
If someone uses your lib, they'd expect to find all of your functionality in your library (namespace-wise). They should not have to look into the docs, or read the source
<Groogy>
yeah I was just curious, was thinking of moving vector impl to VectorImp and just have aliases make it convenient to use and have these operations defined in a Vector module
<Papierkorb>
I assume that you want to publish that as shard eventually?
<Groogy>
haven't really thought of it no, maybe
<Groogy>
right now it's just my project to learn the language
<Groogy>
porting various parts of my game projects to see how would I implement it in Crystal
<Papierkorb>
If yes, then you'll want to put *everything* into its own module ("namespace"). If your shard will be called .. .. erm .. `veccy`, then the module is called `Veccy`, and in there, you have your Vector struct, etc.
<Groogy>
I would probably shorten it though since doing ProjectName::Vector everywhere would be annoying
<Groogy>
though project this comes from is named Ego so wouldn't be that long
<Papierkorb>
w.r.t. `Math`, I was assuming library code ;) For application code, you can of course do as you please. Applications can freely reign over the environment, but libraries should keep it to a minimum as to not cause unexpected clashes with other libraries or application code
<Groogy>
well as you say I should probably keep in mind of "sharing it"
<Papierkorb>
Choose a short name, yes. The module name (CamelCase) should be the same as the library name (canonical is snake_case). The command `crystal init lib ego` will set you up with all of that
<Groogy>
though if I would want to share things I would probably work on it a bit more
<Groogy>
like letting you set a Bit on the matrix to say if it is left or right handed order, etc.
<Groogy>
right now I am just assuming OpenGL
<Groogy>
though would be awesome to just port glm lib somehow, because that library is awesome
sz0 has joined #crystal-lang
Sh4DoW has joined #crystal-lang
Sh4DoW has quit [Client Quit]
rohitpaulk has quit [Remote host closed the connection]
raz has joined #crystal-lang
ome has joined #crystal-lang
t-richards has joined #crystal-lang
tzekid has quit [Remote host closed the connection]
greengriminal has joined #crystal-lang
sz0 has quit [Quit: Connection closed for inactivity]
rohitpaulk has joined #crystal-lang
rohitpaulk has quit [Ping timeout: 240 seconds]
rohitpaulk has joined #crystal-lang
greengriminal has quit [Quit: This computer has gone to sleep]