ChanServ changed the topic of #crystal-lang to: The Crystal programming language | | Fund Crystal's development: | GH: | Docs: | Gitter:
<FromGitter> <> If you do a typeof on that variable, it should show a union type of String|Int. You can restrict it by declaring a variable to be of a certain type, like ⏎ ⏎ ```test : Int32 = 5 ⏎ test = "foo" # compiler error``` []
<FromGitter> <> The automatic union typing has caused me many headaches ^_^;
<FromGitter> <> As has the lack of a `let` since a typo can declare a new variable
<irc_user> I thought that might be the case but earlier I tried `test = "hello"; puts typeof(test); test = 5; puts typeof(test)` it prints String then Int, not union. Is there any runtime performance benefit to declaring the type?
<FromGitter> <> with the M2 released today i wonder why people still obsess so much over "performance" when comparing languages. CPU's have become so stupid fast. crystal is on the top end of fast languages. productivity is what matters. in the very rare case you really need to ooze out the last 10% you can still write that part in rust or C.
<FromGitter> <Blacksmoke16> irc_user: the compiler is smart enough to see you're overriding the value of `test`, so there is no possible case where there is a union
<irc_user> I understand where you're coming from, I'm curious though because I don't have the background most older developers do so I don't know what the implication of certain design decisions are.
<FromGitter> <Blacksmoke16> prob would be a marginal compile time hit, given it needs to parse/process that restriction
<FromGitter> <> I declare all my types for sanity reason. The performance shouldn't take too much of a hit since, as i understand, it's all inferred at compile time.
<FromGitter> <Blacksmoke16> also worth pointing out `typeof` returns the compile time type of the variable, you can use `.class` method to get the runtime type
<FromGitter> <> Ahh true, good catch
<irc_user> Ah I see, thanks guys. I really like the option to declare types. Seems like you can iterate on stuff really quickly and still have the option of going back and refining everything.
<irc_user> Right when I found Crystal I wrote game of life and it took me less than an hour, no prior knowledge. Tried to do it in Rust, I gave up after an hour XD
<FromGitter> <> Yeah exactly. You can often forgo types at first, and therefore have the flavor of a dynamic language, but you can type things to make sure your code is correct at compile time later on. At least that's been my approach.
<FromGitter> <> yeh, rust is for language nerds. crystal for people who just want to get stuff done. :)
<irc_user> Yeah I've really been starting to follow that pattern a lot more, not with types but with write bad code to see if an idea is good then refactor once it works. Now with Crystal I can do that with types too.
<irc_user> Haha, with Rust then I get caught in a catch-22, because I feel dumb for not being good at it so it makes me want to learn it.
<irc_user> But I have to pick my battles I guess.
<FromGitter> <> I've used the same pattern for years in Common Lisp. I feel supported during my exploratory phases, and supported during my production phase. That's kinda why I like Crystal, it makes me almost as productive as when I do Lisp.
<FromGitter> <> yup, the ol' rust rabbit hole. in the end you realize you spent the past week doing nothing but fighting the borrow checker. ⏎ then can award yourself a medal for having successfully managed your memory. meanwhile in a less manual language like crystal, you'd have already finished your app.
<irc_user> Wow, that's crazy because I was about to write a project in Common Lisp/Scheme before I found Crystal. I was really trying to find out if the "magic" of CL was just hype or not.
<FromGitter> <> at least that's my experience :p
<irc_user> XD I'm sure that would be even moreso the case for me.
<FromGitter> <> irc_user: I've worked in Lisp for far longer than I have in Crystal, so for me the magic is not hype :-P it's just taken a while. I'm kind of an odd one out in that i had no experience in Ruby before Crystal, and i generally don't do web stuff (save for Matrix/Discord bots). For me it was always Lisp, C, Object Pascal, or C#. Now i just use Common Lisp and Crystal for everything. Crystal
<FromGitter> ... is what actually got me to use Ruby for scripting instead of Bash for some things lol
hightower3 has quit [Remote host closed the connection]
hightower3 has joined #crystal-lang
<FromGitter> <> ruby is pretty much just lisp with words instead of braces :p
ur5us has quit [Ping timeout: 255 seconds]
<FromGitter> <> ...and some OO sprinkled in
<FromGitter> <> And without the object system
<FromGitter> <> yea, maybe i was stretching the analogy a bit 😬
<FromGitter> <> I meant ruby is Common Lisp without Common Lisp's object system :-P
<irc_user> Well I'm happy to hear that, maybe I'll still give Lisp a go then. Lisp seemed sort of similar to vim from my perspective, but with vim I had verified that the hype was real after years of use. So I figured Lisp could be the same.
<irc_user> I haven't done any Ruby either, but I have been using Imba which is a super underrated web lang/framework inspired by ruby as well.
<FromGitter> <> ha, i thought i'm the only one who tried imba! :D
<irc_user> Haha, Imba's my favorite right now. I've made entire apps in it without a hitch at all.
notzmv has quit [Ping timeout: 272 seconds]
<FromGitter> <> yea, it turned out a bit too magic for me in the end so i'm leaning towards svelte now. ⏎ (but def gonna keep an eye on imba)
<FromGitter> <> my main concern was that there seems to be only one maintainer and not much usage, yet. ⏎ so didn't wanna invest too much only to see it get abandoned at some point.
<irc_user> I haven't experienced too many issues with magic, the syntax has been mostly straightforward, at least right now. I'm no shill though, you do you XD. Yeah, It's kind of insane how much he's done. But they use that language to build Scrimba, so voluntary abandonment seems very unlikely. Over my couple month-long project, every time I thought I ran into a roadblock with Imba it turned out to be something else's fault.
<irc_user> To be fair I haven't tried anything else though. I was looking into Clojurescript but IMO they haven't made getting into it that easy.
<irc_user> With imba and crystal you run one command and you're up and running.
<irc_user> I think some language authors don't realize how big of a deal that is
<FromGitter> <> very true
ur5us has joined #crystal-lang
notzmv has joined #crystal-lang
<FromGitter> <dorianmariefr> "also i will say you're doing some crazy stuff" @Blacksmoke16 that's a compliment in my book :D
<FromGitter> <dorianmariefr> my little PEG is going well though
<FromGitter> <Blacksmoke16> i would have thought the opposite given all the segfaults you get 😅
<FromGitter> <dorianmariefr> erf, I need to rearchitecture my code for lookahead :(
<FromGitter> <Blacksmoke16> :(
<FromGitter> <dorianmariefr> #dup to the rescue, liking crystal so far
<FromGitter> <Blacksmoke16> do note thats a shallow copy. idk if it makes a diff for your use case or not
<FromGitter> <dorianmariefr> yeah I would not want my `@buffer` to be shared across instances
<FromGitter> <dorianmariefr> is there a way to filter out the "/Users/dorianmariefr/.asdf/installs/crystal/1.4.1/src/spec/ in 'internal_run'" lines from the backtrace? (except by monkey patching)
<FromGitter> <Blacksmoke16> for what reason?
<FromGitter> <dorianmariefr> I've got 13 lines of crystal backtrace and 3 lines of my code backtrace. Most of the times I'm not digging in crystal internals but would rather just see my code's backtrace
<FromGitter> <dorianmariefr> rspec has backtrace filtering
<FromGitter> <Blacksmoke16> are you manually printing the backtrace or?
<FromGitter> <Blacksmoke16> oh i think i know what you're running into
<FromGitter> <Blacksmoke16> make sure your spec examples are within an `it` block
<FromGitter> <dorianmariefr> So.... I guess I need a `#deep_dup`
<FromGitter> <dorianmariefr> :D
<FromGitter> <Blacksmoke16> whats the code look like?
<FromGitter> <dorianmariefr> is where I'm at
<FromGitter> <dorianmariefr> need to figure out the ".ignore" now
<FromGitter> <Blacksmoke16> ah so there's an exception when you dont expect there to be one
<FromGitter> <Blacksmoke16> you prob want `#clone`
<FromGitter> <dorianmariefr> "Error: undefined method 'clone' for Language::Parser"
<FromGitter> <dorianmariefr> it's not on `Object#clone`?
<FromGitter> <Blacksmoke16> no, for custom types you need to define what it does
<FromGitter> <Blacksmoke16> can maybe just use this tho
<FromGitter> <dorianmariefr> hmmm, trying it, I think I actually might have a logic-issue
<FromGitter> <Blacksmoke16> oh?
<FromGitter> <dorianmariefr> So I can'
<FromGitter> <Blacksmoke16> what does it do? denote the application should have extra debug logic?
<FromGitter> <dorianmariefr> Oh, maybe I should have an `ENV["DEBUG"]` instead, it's to print debug messages when in debug mode
<FromGitter> <dorianmariefr> e.g. `puts "something" if debug?`
<FromGitter> <Blacksmoke16> you have a few options depending on how you want it to work
<FromGitter> <dorianmariefr> also why is there no `.present?` but there is `.presence`
<FromGitter> <Blacksmoke16> 1) Use the `Log` module, allows libs to configure what gets logged. Tho only useful for messaging ⏎ 2) Use a compile time flag, allows totally removing the debug logic from the binary, but needs to be rebuilt to add it back ⏎ 3) Use an env var to control if it should print
<FromGitter> <Blacksmoke16> what would `.present?` do? Return true if its no nil or?
<FromGitter> <dorianmariefr> `!!object.presence` I guess
<FromGitter> <dorianmariefr> Yeah I guess a logger would be the correct way to do it
<FromGitter> <Blacksmoke16> !object.nil?
<FromGitter> <dorianmariefr> would be `!object.empty?` for hash, array, string
<FromGitter> <dorianmariefr> I know ruby doesn't want to implement it :)
<FromGitter> <Blacksmoke16> i always thought adding an overload of `.presence` would work well
<FromGitter> <Blacksmoke16> for collection types. that only return `self` if its not nil and not empty
<FromGitter> <Blacksmoke16> then you can do like
<FromGitter> <Blacksmoke16> ```return unless (arr = array.presence)```
Vexatos_ has joined #crystal-lang
lanodan has quit [Ping timeout: 246 seconds]
Vexatos has quit [Ping timeout: 246 seconds]
lanodan has joined #crystal-lang
<FromGitter> <dorianmariefr> I do things like: ⏎ ⏎ ```def buffer? ⏎ !!@buffer.presence ⏎ end``` []
<FromGitter> <dorianmariefr> I don't understand, there is an `expect_raises` macro (without arguments) but I can't call it: ⏎ ⏎ 31 | expect_raises do ⏎ ⏎ `````` []
<FromGitter> <naqvis> its because you are looking at outdated version
<FromGitter> <naqvis> macros version of `expect_raises` were refactored 4 years before
ur5us has quit [Ping timeout: 258 seconds]
<FromGitter> <dorianmariefr> any reason to not have a default of Exception, e.g. `klass : T.class = Exception`?
<FromGitter> <dorianmariefr> thanks, not sure how I ended up on an outdated version, probably because of google
<FromGitter> <naqvis> will answer your question
irc_user has quit [Quit: Connection closed for inactivity]
notzmv has quit [Ping timeout: 240 seconds]
irc_user has joined #crystal-lang
Sankalp has quit [Ping timeout: 248 seconds]
Sankalp has joined #crystal-lang
onyx has joined #crystal-lang
notzmv has joined #crystal-lang
ur5us has joined #crystal-lang
irc_user has quit [Quit: Connection closed for inactivity]
ur5us has quit [Ping timeout: 255 seconds]
<oz> golang
<oz> haha oops. Wrong chan. :)
_ht has joined #crystal-lang
<riza> ^ banned for that ;-)
<FromGitter> <stellarpower> Thanks! Yes, looks a good idea. I've not really had much of a chance to have a play properly yet, any time I want to try a new technology I sorta have to justify to myself that I can do so whilst at work, and it'll do something better than just using whatever I already have😅. But I'll definitely give this a try. Can set up some useful options as a shel lalias for the crystal compiler, so this is
<FromGitter> ... included automagically when I build. I'#d wanted to do something similar for Ruby for JSON and CSV cause the interface to each is slightly different. I was gonna ifnd the best way of opening each and unify them via a single API so I don't have to rememeber so much. The ability to re-open a class is such a good way things like htis ... []
onyx_ has joined #crystal-lang
onyx has quit [Ping timeout: 260 seconds]
Liothen_ has joined #crystal-lang
kevinsjoberg_ has joined #crystal-lang
analogsalad has joined #crystal-lang
Liothen has quit [Ping timeout: 248 seconds]
kevinsjoberg has quit [Ping timeout: 248 seconds]
kevinsjoberg_ is now known as kevinsjoberg
Liothen_ is now known as Liothen
f1refly has quit [Read error: Connection reset by peer]
f1refly has joined #crystal-lang
<SamantazFox_> Hello!
<SamantazFox_> How can I parse namespaces in XML?
<FromGitter> <Blacksmoke16>
<FromGitter> <Blacksmoke16> gist of it is you need to declare your prefix => uri mappings, then use those in your xpath query
<SamantazFox_> heck D:
<SamantazFox_> So, does it fetches the provided URIs every time parsing is required?
<SamantazFox_> or is it only as a reference?
<FromGitter> <Blacksmoke16> not sure tbh. I always just assumed they're references and not actually fetched or anything
<FromGitter> <RespiteSage> It seems like it would be nice for the parser to read the xmlns declarations and use those.
<SamantazFox_> RespiteSage for a local parser, that could make sense, but in our case, that would make parsing extremely slow
<SamantazFox_> (And in youtube's case, the URI is not even valid)
<FromGitter> <RespiteSage> I was suggesting that it would just identify the namespaces (not follow the URIs) during parsing and keep them to use for things like rpath calls. Is that what you mean would be slow?
<FromGitter> <RespiteSage> So it wouldn't actually follow the URIs to get the schemas, it would just keep track of what schemas were declared.
<FromGitter> <RespiteSage> *what namespaces were declared
<SamantazFox_> RespiteSage Oh, I though you meant downloading the files! Yes, indeed, it being able to keep track of the namespaces declared would be awesome!
<FromGitter> <Blacksmoke16> i vaguely running into this at work with PHP (which also uses libxml iirc). The catch is the XML namespace prefix aren't static iirc
<FromGitter> <Blacksmoke16> this issue from `oq` has some helpful explanations of how it works (and why its so confusing)
<FromGitter> <Blacksmoke16> the prefixes of the namespaces rather*. It's really a pita :/
<FromGitter> <RespiteSage> Is is semantically valid to reassign a prefix to a different namespace within the same node?
<SamantazFox_> heck....
<FromGitter> <RespiteSage> Just as a naive approach I was thinking that when a prefix is encountered you'd just look back at the parent and then its parent, etc., until you find the prefix defined or get to the top level.
<FromGitter> <Blacksmoke16> > Is is semantically valid to reassign a prefix to a different namespace within the same node? ⏎ ⏎ i think so? Given you can have a namespace declared on an inner node, meaning the namespace of unprefixed (or change the namespace of existing prefixes) changes for only those elements
<SamantazFox_> When inspecting the parsed XML, I'm getting this: (cleaned up a bit for readibility)
<SamantazFox_> so why `pp rss.xpath_node("//feed/channelId").try &.content` returns nil?
<FromGitter> <Blacksmoke16>
<FromGitter> <Blacksmoke16> probably because your xpath query isn't declaring/using any namespaces
<FromGitter> <Blacksmoke16> i.e. its only searching nodes not in a namespace, which there are none
<FromGitter> <Blacksmoke16> i.e. you need to declare the default namespace and use your given prefix in the xpath: `rss.xpath_node("//base:feed/base:title", namespaces: {"base" => ""})`
_ht has quit [Remote host closed the connection]
<SamantazFox_> So `XML.parse_html` has none of that constraints
<FromGitter> <Blacksmoke16> guess not given at that point its following a diff spec?
<SamantazFox_> what do you mean?
<FromGitter> <Blacksmoke16> afaik just because they use a similar syntax, they're not related
analogsalad has quit [Quit: bye]
<FromGitter> <Blacksmoke16> like i dont think HTML is an extension of XML. So the semantics of parsing it are different?
<FromGitter> <Blacksmoke16> by extension i mean like the relationship between YAML and JSON*
onyx_ has quit [Read error: Connection reset by peer]
<FromGitter> <Blacksmoke16> or no, maybe that's actually more accurate. E.g. a valid XML document being valid HTML, but valid HTML not being valid XML
<SamantazFox_> hmm, yeah
<FromGitter> <> iirc, isn't HTML an implementation of SGML, while XML is simply a strict subset of it?
ur5us has joined #crystal-lang
jmdaemon has joined #crystal-lang
<FromGitter> <gregoryc> Hi
<FromGitter> <gregoryc> How do I do this def foo(arg : typeof(bar))
<FromGitter> <gregoryc> Anyone here?
<SamantazFox_> Hello!
<SamantazFox_> Be patient, people aren't 24/7 on their PCs :)
<SamantazFox_> You probably want to look at `def foo(arg : T) forall T`
<FromGitter> <RespiteSage> Yeah, `forall` is probably what you need. Could you explain more about what you're trying to do?
<FromGitter> <gregoryc> like T = (expr ..............).class; def foo(arg : T)
<FromGitter> <gregoryc> actually, I'm trying to make a macro
<FromGitter> <gregoryc> I want type constraints based on the type of an expression
<FromGitter> <RespiteSage> Is the type of the expression completely determined at compile-time?
<FromGitter> <gregoryc> yes
<FromGitter> <gregoryc> forall might work
<FromGitter> <gregoryc> I've never used it yet
<FromGitter> <gregoryc> I'm a little confused by this
<FromGitter> <gregoryc> def foo(x : T.class) forall T ⏎ Array(T) ⏎ end
<FromGitter> <gregoryc> Does that make each invocation an overload?
<FromGitter> <RespiteSage> If you have repeated invocations for the same `T`, I believe they'll use the same function specialization, but it'll internally create ones for every `T` you use.
<FromGitter> <RespiteSage> `forall` is incredibly useful for generics:
<FromGitter> <RespiteSage> That method on `Array(T)` takes another method `Array(U)` and returns the `Array(T|U)` of the concatenation.
<FromGitter> <gregoryc> So forall makes a template essentially, like in C++?
<FromGitter> <gregoryc> Generic programming?
<FromGitter> <RespiteSage> There's some similarity there, for sure. I'm not familiar enough with C++ templating to say how close it is.
<FromGitter> <gregoryc> Still not working for me :(
<FromGitter> <gregoryc> I got this def {{name}}(str : String, start : A.class , end_ : B.class, recursion : Bool =false, &block : String -> String) : String forall A, B
<FromGitter> <RespiteSage> Can you make an example of what you're trying to do on, even if it doesn't compile?
<FromGitter> <gregoryc> I'm trying to pass a string and regex to this
<FromGitter> <gregoryc> and make overloads in this macro
<FromGitter> <RespiteSage> Remove the `.class`?
<FromGitter> <gregoryc> That compiles
<FromGitter> <gregoryc> Thank you
<FromGitter> <RespiteSage> Yep! You only want `.class` in a type restriction if you want `Class` types as arguments (i.e. subclasses of
<FromGitter> <gregoryc> Still not the behavior I want
<FromGitter> <gregoryc> I define a string overload and a regex overload
<FromGitter> <gregoryc> And the regex one seems to happen
<FromGitter> <gregoryc> Even though the string should happen
<FromGitter> <gregoryc> I do puts A, B
<FromGitter> <gregoryc> And I get String, String
<FromGitter> <RespiteSage> Without knowing more about your code, I can't really help with that.
<FromGitter> <RespiteSage> If you could make an example of what you're trying to do on, that would help.
<FromGitter> <RespiteSage> That is,
<FromGitter> <gregoryc> I might use that site, however, wait a second
<FromGitter> <gregoryc> seems like an overloading problem
<FromGitter> <gregoryc> Is there a flag to preprocess only?
<FromGitter> <RespiteSage> Uhh... Yeah, there is. I can't remember. Let me see if I can find it.
<FromGitter> <gregoryc> expand?
<FromGitter> <gregoryc> cant make it work
<FromGitter> <RespiteSage> `crystal tool expand`?
<FromGitter> <gregoryc> was trying that
<FromGitter> <gregoryc> let me try
<FromGitter> <gregoryc> crystal tool expand [file] not working
<FromGitter> <gregoryc> Doesn't work
<FromGitter> <gregoryc> Alright, I have
<FromGitter> <gregoryc> gsub__(gsub_recursive, str[i..i + start.size - 1] == start, str[i..i + end_.size - 1] == end_) ⏎ gsub__(gsub_recursive,str.match(/^#{start}/), str.match(/^#{end_}/)) ⏎ ⏎ new_text = (gsub_recursive ARGV[0], ARGV[1], ARGV[2] do |i| ⏎ ... []
<FromGitter> <gregoryc> Formatting is bad
<FromGitter> <RespiteSage> Yeah, I can't get `crystal tool expand` to work, either.
<FromGitter> <gregoryc> Do you guys know a tool like rubocop for crystal, i.e., better than tool format ?
<FromGitter> <gregoryc> Wow, that's a nice site
<FromGitter> <gregoryc> OK, I'll share my code, why not
<FromGitter> <gregoryc>
<FromGitter> <RespiteSage> I'm not familiar with `rubocop`, but maybe you'd find ameba ( helpful?
<FromGitter> <gregoryc> Thank you
<FromGitter> <gregoryc> My code works, I'm just trying to make it generic
<FromGitter> <RespiteSage> What are some good `ARGV` inputs for this code?
<FromGitter> <gregoryc> It's like a better gsub that can go recursive
<FromGitter> <RespiteSage> Since doesn't have `ARGV`.
<FromGitter> <gregoryc> Give me a sec
<FromGitter> <gregoryc> crystal code 'cat {dog} frog' '{' '}'
<FromGitter> <gregoryc> ARGV[0] is string, ARGV[1] is beginning string to delete
<FromGitter> <gregoryc> ARGV[2] is ending string to delete
<FromGitter> <gregoryc> and it gets yielded like gsub(....) do |...| ...; end
<FromGitter> <gregoryc> I want to make it generic
<FromGitter> <gregoryc> The code snippet can be used to make parsers, etc.
<FromGitter> <gregoryc> Quite useful I thinkj
<FromGitter> <gregoryc> *think
<FromGitter> <gregoryc> The code was working very well before
<FromGitter> <gregoryc> If i get rid of the regexp one is works just fine
<FromGitter> <gregoryc> Output =>
<FromGitter> <gregoryc> str cat {dog} cat ⏎ str[i..((i + start.size) - 1)] == start ⏎ !dog ⏎ str dog ⏎ str[i..((i + start.size) - 1)] == start ... []
<FromGitter> <gregoryc> cat [ dog ] cat is what I wanted
<FromGitter> <gregoryc> With spaces around it
<FromGitter> <gregoryc> When I add the regex overload (invoking the macro), it messes it up
<FromGitter> <gregoryc> So
<FromGitter> <gregoryc> Why is it not overloading properly?
<FromGitter> <gregoryc> I'll release that snippet into the public domain
<FromGitter> <gregoryc> Because why not
<FromGitter> <gregoryc> Crystal's macro system is insane
<FromGitter> <gregoryc> It's the best that I have seen in any programming language
<FromGitter> <gregoryc> Can anyone help?
<FromGitter> <RespiteSage> I'm sorry, but I'm having trouble following your code, and I need to leave soon.
<FromGitter> <gregoryc> Anyone else then?
<FromGitter> <gregoryc> This doesnt work
<FromGitter> <gregoryc> macro gsub__ (name, cond1, cond2) ⏎ ⏎ #T{{name}} = typeof(cond1) ⏎ ⏎ def {{name}}(str : String, start : A , end_ : B, recursion : Bool =false, &block : String -> String) : String forall typeof(cond1), typeof(cond2) []
<FromGitter> <gregoryc> Is there no macro typeof or decltype?
<FromGitter> <gregoryc> So
<FromGitter> <gregoryc> I got it working
<FromGitter> <gregoryc> But without a decltype or typeof
<FromGitter> <gregoryc>
<FromGitter> <gregoryc> I'm releasing both in the public domain
<FromGitter> <gregoryc> Modify and reuse as you wish
<FromGitter> <gregoryc> This is better
<FromGitter> <gregoryc>