ChanServ changed the topic of #crystal-lang to: The Crystal programming language | http://crystal-lang.org | Crystal 0.34.0 | Fund Crystal's development: http://is.gd/X7PRtI | GH: https://github.com/crystal-lang/crystal | Docs: http://crystal-lang.org/docs/ | API: http://crystal-lang.org/api/ | Gitter: https://gitter.im/crystal-lang/crystal
deavmi has quit [Ping timeout: 260 seconds]
deavmi has joined #crystal-lang
<FromGitter> <Blacksmoke16> 😬
gangstacat has quit [Quit: Ĝis!]
gangstacat has joined #crystal-lang
<FromGitter> <didactic-drunk> Is there a way to get all methods with an annotation on a class in a finished macro?
<FromGitter> <didactic-drunk> And their return values
<FromGitter> <Blacksmoke16> return value no, return type, possibly assuming the method has a restriction set
<FromGitter> <didactic-drunk> Type yes.
<FromGitter> <didactic-drunk> Uh, no restriction.
<FromGitter> <Blacksmoke16> then you wont be able to no in macro land
<FromGitter> <didactic-drunk> But it's called in one place.
<FromGitter> <didactic-drunk> Ok, I'll work around it and add type restrictions.
Vexatoast has joined #crystal-lang
oz has quit [Quit: EOF]
Vexatos has quit [Ping timeout: 258 seconds]
oz has joined #crystal-lang
rocx has quit [Ping timeout: 260 seconds]
alexherbo2 has joined #crystal-lang
alexherbo2 has quit [Quit: The Lounge - https://thelounge.chat]
alexherbo2 has joined #crystal-lang
<FromGitter> <naqvis> thanks. Can you please share the Windows compilation steps? so that i can add them to Makefile?
<FromGitter> <naqvis> currently Makefile only have mac and linux
zorp_ has joined #crystal-lang
tdc has joined #crystal-lang
<FromGitter> <igor-alexandrov> Guys, is there a Crystal alternative to `URI.join` in Ruby? https://apidock.com/ruby/URI/join/class
<FromGitter> <didactic-drunk> Is there a way to show the code a macro generates?
<FromGitter> <naqvis> place `{{debug}}`
<raz> or write some random gibberish into it. the compiler usually dumps the generated macro code for me when it fails :)
<raz> (might only do that with --error-trace, not sure)
alexherbo2 has quit [Quit: The Lounge - https://thelounge.chat]
alexherbo2 has joined #crystal-lang
alexherbo2 has quit [Client Quit]
alexherbo2 has joined #crystal-lang
alexherbo2 has quit [Client Quit]
alexherbo2 has joined #crystal-lang
alexherbo2 has quit [Quit: The Lounge - https://thelounge.chat]
alexherbo2 has joined #crystal-lang
deavmi has quit [Ping timeout: 260 seconds]
deavmi_ has joined #crystal-lang
deavmi_ has quit [Ping timeout: 272 seconds]
deavmi has joined #crystal-lang
yxhuvud has quit [Read error: Connection reset by peer]
yxhuvud has joined #crystal-lang
rocx has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 260 seconds]
<FromGitter> <Blacksmoke16> omg ⏎ ⏎ > then you wont be able to no in macro land ⏎ ⏎ rip [https://gitter.im/crystal-lang/crystal?at=5ecd18c6549761730b5add60]
<FromGitter> <Blacksmoke16> know*
<FromGitter> <watzon> @igor-alexandrov `File.join` works with URLs
<raz> holy smokes, finally a working keyboard again
* raz feels reborn
<FromGitter> <igor-alexandrov> > @igor-alexandrov `File.join` works with URLs ⏎ ⏎ It works, but not as good as `URI.join` in Ruby: ⏎ ⏎ ```File.join("http://example.com", "///a.png") ⏎ => "http://example.com///a.png"``` [https://gitter.im/crystal-lang/crystal?at=5ecd2f064412600ccd6b796c]
JuanMiguel has joined #crystal-lang
<straight-shoota> @igor-alexandrov: https://crystal-lang.org/api/0.34.0/URI.html#resolve(uri:URI%7CString):URI-instance-method
<straight-shoota> => URI.parse("http://example.com").resolve("///a.png").to_s
<straight-shoota> >> URI.parse("http://example.com").resolve("///a.png").to_s
<DeBot> straight-shoota: Error: undefined constant URI - https://carc.in/#/r/95ds
<straight-shoota> >> require "uri"; URI.parse("http://example.com").resolve("///a.png").to_s
<DeBot> straight-shoota: # => "http:///a.png" - https://carc.in/#/r/95dt
Human_G33k has joined #crystal-lang
HumanG33k has quit [Ping timeout: 264 seconds]
JuanMiguel has quit [Quit: This computer has gone to sleep]
JuanMiguel has joined #crystal-lang
<FromGitter> <naqvis> https://carc.in/#/r/95ex
<FromGitter> <naqvis> https://github.com/crystal-lang/crystal/blob/4401e90f001c975838b6708cc70868f18824d1e5/src/uri/uri_parser.cr#L173 is redundant as host will get set in `parse_host` method.
<FromGitter> <didactic-drunk> Can I return early from a macro? ⏎ ⏎ ```macro foo ⏎ {{ return if feature.disabled }} ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5ecd4e3cb101510b201ae6fc]
<jhass> I don't think so, it doesn't really make sense conceptually
<jhass> a macro is a code transsformation step
<jhass> it doesn't actually have a stack frame and thus return value
<FromGitter> <didactic-drunk> Conceptually I want the macro to stop doing whatever it's doing. Similar to `return (nil)`
<FromGitter> <Blacksmoke16> `if/else`
<FromGitter> <didactic-drunk> Yes, but now It's one indentation level deeper/uglier.
<FromGitter> <Blacksmoke16> welcome to macros :p
alexherbo2 has joined #crystal-lang
<jhass> would you expect to be able to return early from a template?
<jhass> macros essentially are templates
<FromGitter> <didactic-drunk> Your talking about implementation details. I'm talking about form and function. It's named. It looks like a function. Yes.
<FromGitter> <Blacksmoke16> user defined macros would help with this
<FromGitter> <Blacksmoke16> as you could then put that logic outside of the template
<FromGitter> <didactic-drunk> What if it wasn't implemented that way and was more like ruby, or even called ruby as a preprocessor step? Not allowing early return makes sense when looking from the bottom up, but not to me when looking from the top down of why can't I do it when I can do it elsewhere?
<FromGitter> <jwoertink> Anyone know if there's any plan to make XML serializable like JSON and YAML?
<jhass> XML is a lot more complex there, I don't see it happening in stdlib tbh
<jhass> but there's nothing stdlib can do that a shard cannot
FromGitter has quit [Ping timeout: 260 seconds]
oprypin_ has joined #crystal-lang
oprypin has quit [Ping timeout: 260 seconds]
FromGitter has joined #crystal-lang
JuanMiguel has quit [Quit: This computer has gone to sleep]
<FromGitter> <sam0x17> I've actually written some basic xml dsl's embedded in projects before, it's not hard if you have a limited domain you're doing it in
<FromGitter> <sam0x17> depending on what you're doing you might also be able to just make use of ECR
<FromGitter> <igor-alexandrov> > *<straight-shoota>* @igor-alexandrov: https://crystal-lang.org/api/0.34.0/URI.html#resolve(uri:URI%7CString):URI-instance-method ⏎ ⏎ Wow! Great.
<Stephie> hey oprypin_, how easy would be to get Process.find_executable working on win32?
<oprypin_> Stephie, i havent looked into it. though i think there was some implementation of it, perhaps by jan_zajic?
<oprypin_> what's it used for, anyway? never ran into it directly
<Stephie> cause, the link handling PR changes the code to use it
<Stephie> if you read the new impl
<oprypin_> oof
<Stephie> so compiler will dep on it
<Stephie> and all the specs are pending_win32
<Stephie> seems like a simple tweak to use Path though
<Stephie> wait it already does
<Stephie> hmm
<Stephie> maybe the specs just need uncommenting??
<oprypin_> maybe
<oprypin_> oh i was thinking of something else then
<Stephie> i should play with it but ugh
<Stephie> i havent had a windows crystal environment for
<Stephie> months
<Stephie> uhh
<oprypin_> yea i was thinking about `executable_path`
<Stephie> years
<Stephie> actually
<Stephie> ahh right
<oprypin_> Stephie, eh it's easy with the VM (that you need to re-setup every few months)
<Stephie> its not too bad but
<oprypin_> i didnt have it on my radar
<oprypin_> let me try `find_executable` now
<Stephie> thanks <3
<oprypin_> Stephie, wait how is it supposed to find "pkg-config" on windows
<Stephie> well, the same way it was before
<Stephie> not
<Stephie> all i care is that the command succesfully fails
<Stephie> and doesnt, blow up
<oprypin_> it's a constant, too, doesn't that add to Crystal's startup?
<oprypin_> i'd run it only if pkg-config is used for the first time
<Stephie> yeah
<Stephie> but its the compiler
<Stephie> taking 200 more us doesnt matter
<oprypin_> but on windows why would it look for pkg-config in all path directories
<oprypin_> disk is slow and like the PATH on windows is huge usually
<Stephie> cause its gonna use pkg-config *every* compile
<Stephie> if you want to never use pkg-config on windows that one thing
<Stephie> i'd like to know if it's ever been used there
<Stephie> right
<Stephie> there's precompiled pkg-config windows deps
<Stephie> so, i'll say yeah people use it on windows
<oprypin_> :o
<oprypin_> the thing about find_executable is, should it find with & without .exe extension?
<oprypin_> it probably should
<Stephie> actually
<Stephie> windows has an env var for path extensions....
<oprypin_> wait it works right now. HOW
<Stephie> PATHEXT
<Stephie> wait what
<Stephie> with .exe??
<oprypin_> no it doesnt im studpid
<Stephie> mood
<Stephie> i'd like to know if cmd will search in path for stuff without ext
<Stephie> we should copy it's behaviour
<oprypin_> no it won't
<Stephie> then, it shouldn't
<oprypin_> anyway, find_executable won't blow up, you can just use it now. it's just wrong
<Stephie> nice
<oprypin_> it'd probably find "pkg_config" somewhere in PATH but not "pkg_config.exe"
JuanMiguel has joined #crystal-lang
JuanMiguel has quit [Quit: This computer has gone to sleep]
zorp_ has quit [Ping timeout: 264 seconds]
<oprypin_> aha find_executable should, i think, match the behavior of what'd work with Process.run
<oprypin_> and ... CreateProcess doesn't look at PATHEXT
<oprypin_> and also it's really weird right now that find_executable is wrong even on posix, because it'll find any file that happens to match with PATH
<oprypin_> going back to windows, expanding stuff like `.bat` is purely a thing shell does
<FromGitter> <stellarpower> The markdown class in the standard library is a work in progress right?
<oprypin_> the way that CreateProcess itself works is literally "if the path doesnt end with .exe, append .exe to it"
<oprypin_> stellarpower, it's abandoned and hidden
<FromGitter> <stellarpower> Ahh XD
<FromGitter> <stellarpower> That would be why my compiler can;t find it
<FromGitter> <stellarpower> I thought it was too old
<FromGitter> <stellarpower> Perhaps it's too new
<FromGitter> <stellarpower> Was there a particular reasn it was abandoned?
<oprypin_> stellarpower, it's known to be incomplete and maintaining markdown as part of standard library is seen as undesirable
<FromGitter> <stellarpower> Fair enough
<FromGitter> <stellarpower> I think it would be useful but like regular expressions it's suffered hugely from too many standards
<oprypin_> https://github.com/icyleaf/markd got the attention instead
<FromGitter> <stellarpower> JSON/YAML at least seem to be set in stone
<FromGitter> <stellarpower> Yeah I've required Markd
<FromGitter> <stellarpower> and thought rather than making a PR if there was an ongoing disciussion about stdlib equivalent was gonna ask where I could share my thoughts
<FromGitter> <stellarpower> Oh also quick question, is there anything equivalent to ruby's `methods` that lets us introspect what I can call on an object?
<FromGitter> <Blacksmoke16> yes but its via macros
<FromGitter> <Blacksmoke16> `{{pp MyClass.methods}}`
<FromGitter> <stellarpower> thank you
hightower4 has joined #crystal-lang
Human_G33k has quit [Ping timeout: 260 seconds]
HumanG33k has joined #crystal-lang
tdc has quit [Ping timeout: 256 seconds]
renich has joined #crystal-lang
<oprypin_> fk, i just ran `crystal tool format` in $HOME
renich_ has joined #crystal-lang
renich has quit [Ping timeout: 256 seconds]
renich_ is now known as renich
<Stephie> jhass, thats a lot of approval haha https://elixi.re/i/1ckbkml8.png
<oprypin_> O_o
<jhass> I have no idea how that happend, I didn't even click twice
<Stephie> haha
<Stephie> i think its just github's websocket thing being broken
<Stephie> cause i left the tab open as you approved
<oprypin_> umm so i just found on Windows that `Process.run("foo\\")` works fine if the file `foo/.exe` exists
<oprypin_> how can I get "the part after last slash" using `Path`? `Path["a/"].basename == "a"` - not good
<Stephie> i think there's a ends_with_slash? or similar
<oprypin_> well there is but that's indirect
<oprypin_> `p.ends_with_separator? ? "" : p.basename` is weird
<straight-shoota> There is no other way
<straight-shoota> paths `a/` and `a` are considered equivalent
<straight-shoota> because paths can't have empty components
<straight-shoota> The difference is only in representation
<straight-shoota> which can have a special meaning depending on the usage context (trailing separator is sometimes used to indicate a directory)
<straight-shoota> So `Path` implementation tries to preserve trailing separators
<oprypin_> straight-shoota, well excuse me. if i have an executable `./foo`, i can't run it as `./foo/`
<straight-shoota> `./foo/` is not a normalized path. If you normalize it, you can execute it
<oprypin_> ok but why would i normalize it
<oprypin_> `crystal eval 'Process.run("/usr/bin/crystal/")'` doesnt normalize it for some reason. and fails
<straight-shoota> That's correct
<straight-shoota> Normalization should not be automatically applied
<straight-shoota> only when requested
<oprypin_> cool
<oprypin_> so. how can I get "the part after last slash" using `Path`?
<straight-shoota> exactly because representation can make a difference in some usage contexts
<straight-shoota> `p.ends_with_separator? ? "" : p.basename`
<oprypin_> alright, thanks
<straight-shoota> "A pathname [...] that ends with one or more trailing slashes shall be resolved as if a single dot character ( '.' ) were appended to the pathname."
<straight-shoota> So `a/` is to be treated as `a/.`, which normalizes to `a`
* straight-shoota thinking
<straight-shoota> But technically `.` refers to a directory, so there might actually be a semantic difference...
<oprypin_> >> Bytes[]
<DeBot> oprypin_: Error: unterminated call - https://carc.in/#/r/95hc
<oprypin_> funny error. `UInt8.slice(, read_only: false)`
<oprypin_> wow how can i write a %w() literal inside a macro
<oprypin_> >> {% begin %} %w(1) {% end %}
<DeBot> oprypin_: Error: undefined method '__temp_25' for top-level - https://carc.in/#/r/95hd
<oprypin_> >> p!({% begin %} \%w(1) {% end %})
<DeBot> oprypin_: Error: undefined method '__temp_26' for top-level - https://carc.in/#/r/95he
<oprypin_> >> p!({% begin %} \\%w(1) {% end %})
<DeBot> oprypin_: Error: undefined method '__temp_26' for top-level - https://carc.in/#/r/95hf
<oprypin_> wait, that one just worked for me
<oprypin_> ah lol carcin has another layer of macros
<FromGitter> <simonhf> hello! newbie question coming up :-)
<FromGitter> <simonhf> I have a working crystal one liner: $ crystal eval --time --progress --error-trace 'h=Hash{"one" => 1, "two" => Hash{"foo" => 3}}; printf %[debug: >#{h}< >%s< >%s< >%s<\n], h["one"], h["two"], h["two"].as(Hash)["foo"];' debug: >{"one" => 1, "two" => {"foo" => 3}}< >1< >{"foo" => 3}< >3< ⏎ Execute: 00:00:00.011405934
<FromGitter> <simonhf> Trying to figure out how to do nested hashes
<FromGitter> <simonhf> In Perl I could do e.g. $h{two}{foo} which is much more compact...
<oprypin_> well you did it fine so far
<FromGitter> <simonhf> How can I get rid of the length ".as(Hash)" part?
<oprypin_> crystal code usually isn't structured that way (and doesn't need to be for real world)
<FromGitter> <Blacksmoke16> id prob avoid using hashes depending on the use case
<FromGitter> <simonhf> If I have a nested hash several layers deep then lines will get very long :-)
<FromGitter> <Blacksmoke16> prob better off with structs
<FromGitter> <simonhf> @oprypin thanks! I write a lot of perl one-liners in my day to day work and am used to using nested hashes... how would you structure the hashes away?
<FromGitter> <stellarpower> Sorry, another newbie question. Can we reference types in their "aliases"? Like ⏎ `Tree = Hash(Node, Union(Tree, Node))` for a recursive structure
<FromGitter> <Blacksmoke16> i also wouldnt use recursive types :P
<FromGitter> <stellarpower> what would be a better way of doing it?
<oprypin_> simonhf, `record A, one : Int32, two : B; record B, foo : Int32; A.new(one: 1, two: B.new(foo: 3))`
<FromGitter> <stellarpower> IN the scenario where I have an AST-style thing
<FromGitter> <Blacksmoke16> similar to https://crystal-lang.org/api/master/JSON/Any/Type.html
<FromGitter> <Blacksmoke16> recursive type using a struct
<FromGitter> <stellarpower> I need to read up on structs
<oprypin_> simonhf, then `p! h.one, h.two, h.two.foo`
<FromGitter> <stellarpower> Think it throws my head a little using ruby-like syntax but C++-style thinking. All for the best but am meeting in the middle
<hightower4> simonhf, right, as oprypin_ suggests, `record` would allow you to elegantly create structs. Another way could be using Tuples or NamedTuples. Yet another way could be using classes. Given those couple methods available, you'd decide on a case-by-case basis which one is best. Or for example, if your hashes always contain just 2 or 3 data types (like ints, strings, or further hashes), you could keep them in three separate hashes, so that each
<hightower4> hash contains key/values of only one type, etc...
<FromGitter> <simonhf> @oprypin thanks! trying to put your snippets into a one liner that works :-)
<FromGitter> <simonhf> @oprypin the first part seems to define the structs, but no reference to h. the second part references h... which has me confused...
<oprypin_> simonhf, oh sorry. `record A, one : Int32, two : B; record B, foo : Int32; h = A.new(one: 1, two: B.new(foo: 3)); p! h.one, h.two, h.two.foo`
<FromGitter> <simonhf> @oprypin that works, thanks!
<FromGitter> <simonhf> trying to wrap my head around this :-)
<FromGitter> <j8r> @Blacksmoke16 Do you think it is ok to yield a namedtuple will all annotations keys (here for `Crystalizer::Field`)
<FromGitter> <j8r> This allows to also set custom keys, I am not sure what to think
<FromGitter> <j8r> On one side it allows to share annotations, but on the other hand a given key with a value may not be interpreted the same for different formats
<FromGitter> <j8r> I may overthink this. For now, just doing this https://github.com/j8r/crystalizer/blob/master/src/deserializer.cr#L57 - will see
<FromGitter> <Blacksmoke16> :thinking:
<FromGitter> <Blacksmoke16> idt that key is right, its not really annotations, more like named_argument users defined on the field annotation
<FromGitter> <j8r> yes
<FromGitter> <j8r> The format implementation will be more or less related to the library, at least official ones. I don't think there will be huge issues then
<FromGitter> <j8r> Now, thinking of a standard `Any` type
<FromGitter> <j8r> The main issue is how to get rid of the `@raw : T`
<FromGitter> <j8r> An just serialize T
<FromGitter> <Blacksmoke16> `any.raw.to_json`?
<FromGitter> <j8r> Ha right, I am noob
<FromGitter> <j8r> I can just set overloads in the formats which does this
<FromGitter> <Blacksmoke16> prob yea
<FromGitter> <j8r> Last thing, the `Type` alias in the Any
<FromGitter> <j8r> I guess generics
<FromGitter> <Blacksmoke16> hm?
<FromGitter> <j8r> For example, in JSON `Hash(String, Any)` and in YAML `Hash(Any, Any)`
<FromGitter> <Blacksmoke16> just `alias Any = JSON::Any | YAML::Any`?
<FromGitter> <j8r> Just see there is `Set(Any)` in YAML... didn't know there are sets un yaml
<FromGitter> <j8r> No, the principle here is to be generic - a single Any type for all possible formats
<FromGitter> <Blacksmoke16> uses same logic as array, but does `Set.new arr`
<FromGitter> <j8r> But why it is not in json?
<FromGitter> <Blacksmoke16> :shrug: just wasnt implemented?
<FromGitter> <j8r> better question: why it is here?
<FromGitter> <Blacksmoke16> just was implemented? :P
<FromGitter> <j8r> Parsing a YAML string can give a set, when?
<FromGitter> <Blacksmoke16> when you do `Set(Int32).from_yaml ---\n- 1\n- 2`
<FromGitter> <j8r> Sure
<FromGitter> <j8r> I mean, in Any
<FromGitter> <j8r> `YAML.parse "whatever"`
<FromGitter> <j8r> I think I will just use generics
<FromGitter> <j8r> I may just set the most widen type union possible, but I don't think it is good
<FromGitter> <j8r> btw thanks
<FromGitter> <Blacksmoke16> πŸ‘ np
<FromGitter> <j8r> Just tried, hum, does not sound possible to have a generic T for a given type T
<FromGitter> <j8r> https://carc.in/#/r/95hx
<FromGitter> <j8r> Quite dumb, because Any need a type of course
<FromGitter> <j8r> found this: https://carc.in/#/r/95i4
<FromGitter> <j8r> Ok perfect :D
<FromGitter> <simonhf> @oprypin "record A, one : Int32, two : B; record B, foo : Int32; h = A.new(one: 1, two: B.new(foo: 3)); p! h.one, h.two, h.two.foo"
<FromGitter> <simonhf> I think I get it :-) But it seems like e.g. a C struct... and not so much like a hash...
<FromGitter> <Blacksmoke16> thats kinda the point πŸ˜‰
<FromGitter> <Blacksmoke16> hashes are usually more of a pain to work with due to the union