<FromGitter>
<noahlh> this feels like a common gotcha but i haven't been able to find the answer: This code throws an `index '0' out of bounds for empty tuple` error and I'm not sure how to handle properly: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5b975d9c728ddf02828ee285]
<FromGitter>
<noahlh> i thought the compiler handles the nil/not-nil case in the if branch, but perhaps not with tuples?
<FromGitter>
<f1refly_gitlab> This isn't nil though, it's an out of bounds error
<FromGitter>
<f1refly_gitlab> Try using `[n]?` instead of `[n]`. It doesn't throw an error but returns nil that you can then handle
<FromGitter>
<noahlh> this is similar to `#first?` which does the same
<FromGitter>
<f1refly_gitlab> It is, but for any index. `#last?` also exists. You can also use `#size` to check the size of the tuple before accessing it
<FromGitter>
<noahlh> ok thank you! -- so going one level deeper -- if I want to call something on that first element if it exists (let's say it's a Tuple of Tuples), I might try something like this:
<FromGitter>
<f1refly_gitlab> If you handle tuples within tuples you can nest this construct or use recursion if applicable
<FromGitter>
<noahlh> right - makes sense
<FromGitter>
<bew> Why are you using a tuple? Would be simpler to use an Array, no?
<FromGitter>
<noahlh> @f1refly_gitlab this code throws the same index out of bounds error though (at least with a Tuple)
<FromGitter>
<f1refly_gitlab> I'd advertise to use a self-defined struct or class. In my experience tuples are messy when you're not handling apis that you didn't design your own.
<FromGitter>
<noahlh> @bew a good question - in the project i'm working on I perhaps mistakenly chose to use Tuples as the data storage mechanism for the object. I'm starting to think that i might be abusing Tuples beyond their intention
<FromGitter>
<f1refly_gitlab> @noahlh Have you tried accessing the inner tuple? If it gets too long please post your code on carc.in
<FromGitter>
<noahlh> ok great - i'll dig in a bit more and see if accessing the inner tuple helps. will share on carc.in for sure.
rohitpaulk has quit [Ping timeout: 240 seconds]
<FromGitter>
<noahlh> actually one more theoretical follow-up before I dive into my own code -- on the code you posted @f1refly_gitlab if I try to access an inner tuple as such:
<FromGitter>
<noahlh> so just so I understand the type system more fully -- @f1refly_gitlab that revised code you just posted above works perfectly. why does that not throw an error?
<FromGitter>
<noahlh> assigning the union type to a variable handles the nil case?
<FromGitter>
<bew> The if handles the nil
Groogy1 has joined #crystal-lang
<FromGitter>
<f1refly_gitlab> Because the function `first?` has the return type `Nil | Tuple`. To be honest i'm not sure if llvm isn't smart enough to defect the only type the first element of the tuple has to be not `nil` at this point or if it wants to protect you from changes made by other fibers. Like @bew said, the if excludes the possibility that `outer` is `nil` because `outer` is a local variable that is save from other fibers
<FromGitter>
<noahlh> ahhhhhhhhhhhh
<FromGitter>
<noahlh> right back to the local variable issue again -- that has been getting me over and over
<FromGitter>
<f1refly_gitlab> I'm tripping about the multi-process logic myself occasionally
<FromGitter>
<noahlh> but assigning to a local variable as you did does not throw the error
<FromGitter>
<noahlh> ok this is going to take some more getting used to but I understand now. @bew and @f1refly_gitlab thank you very much!
<FromGitter>
<noahlh> one day I'll learn :)
<FromGitter>
<f1refly_gitlab> Happy to help
<FromGitter>
<bew> @noahlh because the compiler doesn't know that the second time you call `t.first?` it'll return the same thing when
<FromGitter>
<bew> The same thing as the first time
<FromGitter>
<f1refly_gitlab> Thinking of it - do you know what would be really handy? A way to tell the compiler that you don't want to use fibers. That way, type checking could go way deeper and it would be way easier for beginners
<FromGitter>
<bew> @f1refly_gitlab how so?
<FromGitter>
<f1refly_gitlab> Like probably many others, i'm a self taught user. The "learn" section of the crystal website isn't exactly clear about how types and fibers act together, so i spent way too much time not understanding what the hell i was doing wrong, when the only thing going wrong was the compiler typechecking variables that *could* be modified by fibers. At that point the concept of fibers was weird to me, because i
<FromGitter>
... didn't declare any explicitly
<FromGitter>
<f1refly_gitlab> The tutorial should be more clear about that, with a bigger section on how fibers can be a tripwire for the unaware
flaviodesousa has joined #crystal-lang
flaviodesousa has quit [Remote host closed the connection]
flaviodesousa has joined #crystal-lang
jokke has quit [Ping timeout: 268 seconds]
thews has joined #crystal-lang
<FromGitter>
<bew> you can have the same issues without the "fiber" feature. Just do a function that returns either nil you something else, and get the same behavior..
<FromGitter>
<f1refly_gitlab> Yeah, but the compiler could exclude the possibility of a variable being nil. if yo u were to compile the example above without fibers the compiler could be sure that `t` does in fact return the same value for `#first?` every time. That would be very helpful for beginners who are unaware of the issue
jokke has joined #crystal-lang
<FromGitter>
<drum445> Morning guys, does anyone know how to covert a string into a Slice(UInt8)?
<FromGitter>
<bew> @ninetailschris it's not the full error, can you give what's after?
rohitpaulk has quit [Ping timeout: 244 seconds]
<FromGitter>
<bew> @vladfaust you're overwriting the method with another method, both methods have the same signature, so the 2nd one will dismiss the first one
<FromGitter>
<bew> please add backquotes around code, so it doesn't auto format in gitter, ty
<jokke>
sorry
<FromGitter>
<vladfaust> `(**foo : **T)`, yes
<jokke>
`foobar(**foo : **T) : forall T
<jokke>
ugh
<jokke>
`foobar(**foo : **T) : forall T`
<FromGitter>
<bew> ^^
<FromGitter>
<bew> yes I think that's it
<jokke>
hm okay
bmcginty has quit [Ping timeout: 240 seconds]
bmcginty has joined #crystal-lang
DTZUZO has joined #crystal-lang
shalmezad has joined #crystal-lang
<FromGitter>
<bajro17> I look on official website but I cant find any example how to use route or render for example HTML page can anyone give me example please
<FromGitter>
<vladfaust> @bajro17 HTML page is basically a text. To render it from a template, you can use https://github.com/jeromegn/kilt
<FromGitter>
<bajro17> Thank you and what about routing?
<FromGitter>
<bajro17> m'I need use any shard or I can do it with stdlib?
<FromGitter>
<vladfaust> You should use a shard for that
<RX14>
@vladfaust you've been opening a lof of issues lately, please ask on gitter first...
bmcginty has quit [Ping timeout: 244 seconds]
<FromGitter>
<j8r> Spammerfaust, lol 😄
<FromGitter>
<j8r> a new weapon of mass destruction
<FromGitter>
<vladfaust> @RX14 in my defence, 4 of 13 issues are labelled as bugs and 2 as feature requests! And also those enum-related issues lead to meaningful conversations
<FromGitter>
<vladfaust> It would be nice to be able to `def foo(bar : Array(String) = new)`, because if `def foo(bar = Array(String).new)`, it wouldn't restrict `bar` argument to `Array(String)`.
<FromGitter>
<straight-shoota> `new` would resolve in the current scope (=type scope). Changing that to mean `Array(String).new` would be confusing
<FromGitter>
<j8r> or else adding a new syntax like `def foo(bar := Array(String).new)`, may be also confusing
<FromGitter>
<j8r> nor i dunno it's (cleanly) feasible
<FromGitter>
<vladfaust> `:=` seems interesting
<FromGitter>
<vladfaust> "zoidberg notation"
<FromGitter>
<j8r> Haha, inspired by the current `||=`. R.I.P Futurama ;-(
lvmbdv has joined #crystal-lang
lvmbdv has quit [Client Quit]
shalmezad has quit [Quit: This computer has gone to sleep]
shalmezad has joined #crystal-lang
<RX14>
@straight-shoota fyi your path PR will probably be reviewed in the next week or two
<FromGitter>
<straight-shoota> great!
<RX14>
@straight-shoota I really really don't want to introduce entire classes which are platform-specific into the public API
<RX14>
and I'm fairly unconvinced that an absolutely minimal registry implementation to do this one specific job will be too long
<FromGitter>
<straight-shoota> It's not just one job
<FromGitter>
<straight-shoota> It's time zone names and mime database. Probably also stuff like arbitrary user's home directory.
<FromGitter>
<straight-shoota> but yeah, they all need roughly the same features
<RX14>
why not shell out to reg.exe
<RX14>
i really don't want a registry impl in the public api, for all the reasons I said on the doc PR
<FromGitter>
<straight-shoota> I actually don't really follow these reasons.
<RX14>
types spread really really far in codebases
<RX14>
if you remove one the whole codebase collapses
<FromGitter>
<straight-shoota> But typically, you don't keep open registry handles around
<RX14>
having types on one platform not another is dangerous
<FromGitter>
<straight-shoota> There little need to store them, just the returned values which are basic data types
<RX14>
people'll do it anyway
<RX14>
and it sets a presedent
<RX14>
precedent
<FromGitter>
<straight-shoota> I don't see much danger as it will instantly fail to compile
<RX14>
that IS the danger
<FromGitter>
<straight-shoota> why? I think that's completely safe.
<RX14>
a program should always compile for all platforms if it depends only on the stdlib
<RX14>
it's a lot easier to control platform-specific behaviour at runtime than compile time
<RX14>
because compile-time means you have to ifdef everywhere
<FromGitter>
<straight-shoota> Yeah, I agree on that principle. But compile-time instantly shows you if some specific behaviour won't work on the target platform.
<FromGitter>
<rishavs> Is there a way to declare a public folder for my http server from where i can serve my js/css files? Can't find it in the api docs
<RX14>
@straight-shoota basically the only things in the stdlib that will always fail on windows is fork
<RX14>
and maaaybe a few small other things on process that nobody ever uses like the process group id
<FromGitter>
<j8r> @rishavs you can choose whatever directory, and put it in a variable
<FromGitter>
<straight-shoota> Yes. For these things which are only parts of a bigger API, it is best to fail at runtime
<RX14>
and I want to keep it that way
<RX14>
@straight-shoota honestly for the Crystal::System use you can get rid of all the objects and whatever and be left with only a library of functions that take handles and do various things
<RX14>
I can't imagine that thats much code
<RX14>
so I don't like the idea and I also don't think it's neccesary
<RX14>
if it comes to that point i'll prove it to myself by trying to write a minimal registry implementatioh
<FromGitter>
<rishavs> @j8r was hoping that the stdlib server had this. But thanks, will go ahead and try it
<FromGitter>
<straight-shoota> RX14, sure, it's possible and if you reduce it to the bare minimum, it's gonna be relatively small compared to the PR. But it still doubles much of the functionality and I hate to have to maintain different implementations of the same thing.
<RX14>
it'll be very low maintenance
<RX14>
and i doubt many of the same bugs will appear in both
<FromGitter>
<straight-shoota> yeah, maybe
<FromGitter>
<straight-shoota> I gotta go, bye
<RX14>
cya :)
<FromGitter>
<j8r> see u
<RX14>
@straight-shoota if you look at the history of the go impl there's basically no churn at all
<FromGitter>
<vladfaust> @j8r I'm not so happy about that :D
<FromGitter>
<rishavs> @bajro17 thats what I linked :D ⏎ btw, if you are looking for a web project which is built only using the crystal std lib (routing, templates etc), have a look here https://github.com/rishavs/silver
<FromGitter>
<vladfaust> Yes, but I need `undelete`
<RX14>
"If a set starts with a ^, it is negated"
<RX14>
from the in_set? docs
<FromGitter>
<vladfaust> And, that's what I want
<RX14>
.delete("^A-Za-z0-9")
<FromGitter>
<vladfaust> 👍
<FromGitter>
<j8r> Doesn't work `.rstrip '\u{0}'`
<FromGitter>
<j8r> Or just strip in this case?
<FromGitter>
<vladfaust> Thank, but no. Those guys can be anywhere in the string
<FromGitter>
<vladfaust> @asterite I'm catching `ambiguous call, implicit cast of :writer matches all of User::Role`, while `enum User::Role` contains `Writer`, `Moderator` and `Admin`. Hard to reproduce. Any clues?
wontruefree has joined #crystal-lang
wontruefree has quit [Quit: bye]
bmcginty has quit [Ping timeout: 252 seconds]
bmcginty has joined #crystal-lang
<FromGitter>
<bew> What's the restrictions on that setter?
sagax has joined #crystal-lang
<FromGitter>
<vladfaust> Yes, @bew, I got it reproduced
<FromGitter>
<vladfaust> Trying to reproduce it on carc, got https://carc.in/#/r/4y1c working. However, in my code, this would raise as descripted; and if change `property` to `getter` (i.e. not redefining setter), it compiles and works
wontruefree has joined #crystal-lang
<FromGitter>
<bew> Is your code public?
<FromGitter>
<vladfaust> Not yet. I'll call you when it's released (in couple of days)
<FromGitter>
<bew> Ok
bmcginty has quit [Ping timeout: 245 seconds]
bmcginty has joined #crystal-lang
<FromGitter>
<straight-shoota> RX14, the Go implementation used in the stdlib is actually maintained in the sys package and only imported from there. Not saying that it has more commits there, but it's a different architecture.
<RX14>
@straight-shoota if you compare their histories I actually don't think thats the case
<RX14>
none of the commits are "copy changes from xyz" and i actually think the pacjages have diverged