ChanServ changed the topic of #crystal-lang to: The Crystal programming language | http://crystal-lang.org | Crystal 0.31.1 | 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
Nekka has quit [Ping timeout: 276 seconds]
<FromGitter> <asterite> Kai: you mean for if...then, etc? It might be good for oneliners, I don't know. You can open an issue to discuss it
<FromGitter> <asterite> oh, the "pipe operator" then... I think it was discussed in the past, I can't remember
Nekka has joined #crystal-lang
Human_G33k has quit [Ping timeout: 240 seconds]
Human_G33k has joined #crystal-lang
Human_G33k has quit [Remote host closed the connection]
Human_G33k has joined #crystal-lang
_whitelogger has joined #crystal-lang
<FromGitter> <tenebrousedge> @asterite ⏎ ⏎ ```class Object ⏎ def then``` [https://gitter.im/crystal-lang/crystal?at=5dafac09ef84ab37867d40e2]
<FromGitter> <tenebrousedge> it's sort of complimentary to `tap`
<FromGitter> <meltheadorable> @alehander42 besides the anti-lgbt stuff he constantly posts pretty heinous anti-abortion propaganda while representing the opal project, and it’s still true that the code of conduct doesn’t include any anti-discrimination language - i can’t make a choice to support or use a technical platform on my projects that won’t protect the interests of me, my coworkers, and my friends, and where in order
<FromGitter> ... to keep up with news and talks about it, i’d also need to subject myself to an unending stream of propaganda opposing feminism and womens’ rights
<FromGitter> <sam0x17> I really wish I had known that about opal when I was fiddling around with it
<FromGitter> <sam0x17> for my purposes it was way too slow, but that's really unfortunate all around -- hate to think I indirectly supported that
<FromGitter> <sam0x17> and I say this as a man with a husband
<FromGitter> <meltheadorable> it’s pretty off-topic for here so i don’t wanna spill a lot more words about it, but it’s rough
<FromGitter> <sam0x17> in general though my whole opinion on stuff like opal at this point is "wait for web assembly to deliver"
<FromGitter> <sam0x17> though being able to compile to js is always nice (nim, etc)
<FromGitter> <meltheadorable> Unfortunately it seems like DOM interaction was scoped out of webassembly
<FromGitter> <sam0x17> thats... an oversight
<FromGitter> <sam0x17> lol
<FromGitter> <meltheadorable> so it’ll never deliver
<FromGitter> <meltheadorable> yeah it sucks
<FromGitter> <tenebrousedge> D:
<FromGitter> <sam0x17> ive seen some rust examples that do some cool stuff
<FromGitter> <tenebrousedge> so we're stuck with JS forever‽
<FromGitter> <sam0x17> I doubt it
<FromGitter> <meltheadorable> maybe they still intend to eventually allow webassembly to access the DOM
<FromGitter> <meltheadorable> but it’s been years and there’s been no progress on that front and the site says this now ⏎ ⏎ > "By itself, WebAssembly cannot currently directly access the DOM; it can only call JavaScript, passing in integer and floating point primitive data types. "
<FromGitter> <meltheadorable> regardless
<FromGitter> <meltheadorable> maybe someday
f1refly has quit [Ping timeout: 250 seconds]
<FromGitter> <tenebrousedge> I pray for the day when JS will no longer be necessary. I don't even care what replaces it
f1refly has joined #crystal-lang
<FromGitter> <meltheadorable> i care what replaces it but i do sincerely hope we get a version of webassembly someday that allows DOM interaction
<FromGitter> <meltheadorable> i think the big weird thing is garbage collection
<FromGitter> <sam0x17> nothing stopping people from starting to write the next-gen web assembly-based frameworks now with js glue that handles DOM interaction and will eventually be replaced when they make the web assembly API better
<FromGitter> <sam0x17> other than the fact that rust is really the only one with full full support atm
<FromGitter> <sam0x17> I bet it could still be faster than jquery etc in terms of dom manipulation
<FromGitter> <meltheadorable> not really my area of expertise tbh
<FromGitter> <sam0x17> unless the web assembly <=> js bridge is quite slow
<FromGitter> <sam0x17> the day crystal web assembly support drops I'll start writing a framework
<FromGitter> <sam0x17> regardless of the current web assembly API state
<FromGitter> <tenebrousedge> well, can't you compile to llvm-ir and convert that to wasm?
<FromGitter> <meltheadorable> and lately i’m a little more inspired by things like phoenix liveview which uses dom diffing and websockets to allow writing the frontend in the backend, basically
<FromGitter> <sam0x17> @tenebrousedge probably, not my area of expertise xD
<FromGitter> <sam0x17> that sounds nice tbh
<FromGitter> <tenebrousedge> it would be interesting to try running a "Hello, world!" binary. Maybe I'll try that tomorrow
<FromGitter> <sam0x17> in crystal?
<FromGitter> <tenebrousedge> yeah
<FromGitter> <sam0x17> if you're doing rust, they have a game of life demo that is quite good
<FromGitter> <sam0x17> ah
<FromGitter> <sam0x17> yeah totally
<FromGitter> <sam0x17> def let me know how that goes
<FromGitter> <meltheadorable> i’m oversimplifying a little but it’s neat https://github.com/phoenixframework/phoenix_live_view
<FromGitter> <tenebrousedge> kk
<FromGitter> <meltheadorable> and idk how well that approach would work outside of elixir
<FromGitter> <meltheadorable> or what its failure modes look like
<FromGitter> <meltheadorable> but being able to maintain all the state on the server while still driving real-time behavior
<FromGitter> <meltheadorable> is a biiiiiiiiiiiiiig win
<FromGitter> <meltheadorable> and eliminates a LOT of sync issues
<FromGitter> <meltheadorable> wholesale
<FromGitter> <sam0x17> totally
<FromGitter> <sam0x17> it's a cool concept
<FromGitter> <meltheadorable> yeah i’m keeping a close eye on it
<FromGitter> <sam0x17> side note, in general I think one of the big wins of web assembly would be having some shared logic between server side models and their client-side counterparts, that would lend itself really well to having graphql actually make sense and feel natural
<FromGitter> <meltheadorable> graphql is something i have mixed feelings about but i’m not sure how sharing frontend & backend logic helps
<FromGitter> <sam0x17> if you have a framework that encompases front and backend like that, it could easily auto generate a lot of the graphql type things imo
<FromGitter> <sam0x17> like write a server side model, the framework creates a bunch of the client side pieces for it automatically, with accompanying graph ql schema
<FromGitter> <meltheadorable> i’m still not seeing it - the hard part of graphql seems to be the query backend, permissions, and mutation logic which doesn’t seem to have much to do with logic sharing
<FromGitter> <sam0x17> it's just a hunch
<FromGitter> <meltheadorable> like the difficult part of a graphql server is making the graph schema navigable
<FromGitter> <meltheadorable> using the underlying query mechanisms in your framework
<FromGitter> <meltheadorable> and then making that performant
<FromGitter> <meltheadorable> but that’s entirely between the server & data stores
<FromGitter> <meltheadorable> one of the reasons i think that btw is because one of the benefits of GraphQL is that it allows querying that *doesn’t* reflect the way the data is modeled in the backend, and pulling unexpected bits of data from associated models together in a way that fits your client’s use case, GraphQL would only provide minor benefits over a REST-style API for a backend & a frontend designed with each other in
<FromGitter> ... mind
<FromGitter> <meltheadorable> so autogenerating client models that reflect the exact backend schema only takes you so far when one of the reasons you choose GraphQL in the first place is the flexibility to support very *different* frontend/client use cases
<FromGitter> <meltheadorable> which is why it’s so good for like, public APIs where you don’t know what kinds of apps people may want to make, where the API is the service, or for unifying a query interface over a bunch of unrelated data stores
<FromGitter> <meltheadorable> it disconnects the query interface from the database structure
<FromGitter> <meltheadorable> and from the underlying modeling structure of the application
<FromGitter> <meltheadorable> (to an extent)
<FromGitter> <sam0x17> right, I haven't used graphql at all but the fact that you have to write schemas at all tells me it isn't what I hoped it would be
<FromGitter> <meltheadorable> i’m not sure what you hoped it would be but now i’m curious :P
<FromGitter> <sam0x17> what I'm hoping for is "here are my server side models + permissions on those models + whitelist of fields that are allowed to be transferred to client side", automatically give me a client-side ORM for querying against those, however I want, that is secure and performant, oh and it should automatically create database indexes for me too based on usage
<FromGitter> <sam0x17> I don't think that's a physically impossible thing
<FromGitter> <tenebrousedge> that last one is hard
<FromGitter> <sam0x17> true
<FromGitter> <meltheadorable> but yeah it has major shortcomings imo as well - it would really shine for one or two things my company is doing right now, where the relationship between things is pretty clear and there’s no major modeling challenges but where we want to support a bunch of apps that want to connect the data in VERY different ways
<FromGitter> <meltheadorable> a REST API works but it puts a lot of work on the clients which have to hammer a bunch of endpoints for the data
<FromGitter> <sam0x17> right, and with something like what I just said, you could just start writing client side ORM code and it would magically work
<FromGitter> <sam0x17> it could also be that graphql is the right abstraction, but we need a client-side ORM on top of it
<FromGitter> <meltheadorable> the main shortcoming GraphQL has for me is you can’t specifcy permissions in the schema - I’d like to be able to associate attributes and mutations with like, OAuth Scopes, so that you could do some code generation based on the schemas and enforce permissions on queries
<FromGitter> <tenebrousedge> @sam0x17 I used this (https://github.com/jsonapi-suite/jsorm) for a more or less similar purpose. It required defining a serializer on the backend, and declaring fields in the frontend, and the app was based on a graph database
<FromGitter> <sam0x17> @meltheadorable oh yeah permissions would have to be heavily integrated into this for it to be useful at all
<FromGitter> <meltheadorable> but end of the day graphQL is still a layer over top of the data stores, so I don’t think interaction with the indexing is entirely plausible
<FromGitter> <sam0x17> yeah that last bit is more a wish than a realistic item
<FromGitter> <meltheadorable> and GraphQL doesn’t actually do “graphy” queries making its name sooooort of awkward, so I don’t know that graph databases even particularly save us
<FromGitter> <sam0x17> right, it also annoys me that it isn't its own database, it's more of a proxy
<FromGitter> <sam0x17> I want a magic box that does everything xD
<FromGitter> <meltheadorable> i think that’s both a strength and a weakness
<FromGitter> <meltheadorable> GraphQL being an abstraction pattern is powerful for combining data from a lot of sources
<FromGitter> <meltheadorable> which is a major enterprise use case that’s probably less interesting for apps that aren’t trying to glue together a lot of legacy systems
<FromGitter> <sam0x17> put that way, you're totally right
<FromGitter> <meltheadorable> i think Neo4j has some support for GraphQL-like queries against its schema
<FromGitter> <meltheadorable> when you aren’t doing legacy apps
<FromGitter> <meltheadorable> which would help that some
<FromGitter> <meltheadorable> but you still have the same permissions-based filtering problem
<FromGitter> <meltheadorable> and when your query patterns are against a “native” database instead of as an abstraction pattern
<FromGitter> <sam0x17> well, I now feel less bad about my desire to write my version of what I thought graphql was without trying graphql
<FromGitter> <meltheadorable> you have to either query everything and then do all permissions-based filtering in a proxy
<FromGitter> <meltheadorable> or disallow direct GraphQL queries
<FromGitter> <meltheadorable> and query only for the allowed data in your app acting as a proxy
<FromGitter> <tenebrousedge> neo4j has its own query language; it's safer to say you can do some SQL-like queries
<FromGitter> <sam0x17> ah ok
<FromGitter> <meltheadorable> Neo4j has several query languages, one of them is a GraphQL-alike
<FromGitter> <meltheadorable> https://neo4j.com/developer/graphql/
<FromGitter> <meltheadorable> this is why I would love for GraphQL schemas to provide some mechanism for scope-based filtering
<FromGitter> <meltheadorable> like i said - mixed feelings on GraphQL ^_^
<FromGitter> <meltheadorable> and graph databases generally
<FromGitter> <meltheadorable> but i’d really like to see a web framework designed around being backed by a graphlike database
<FromGitter> <meltheadorable> most are designed with a relational DB in mind
<FromGitter> <sam0x17> are graph-based databases useful beyond writing a social network or doing some kind of spatial/geographic stuff?
<FromGitter> <meltheadorable> Yes and no
<FromGitter> <meltheadorable> They’re good for any application where the utility comes from modeling graphlike human systems - think about something like Goodreads, where even if you take out all the social features, one of the more interesting qualities of the data is the interconnectedness of it — imagine being able to query goodreads by all the books that have Darth Vader as a character, or look at the connections between
<FromGitter> ... authors and publishers, all the books containing pieces by specific authors
<FromGitter> <sam0x17> yeah I really need to get into that stuff
<FromGitter> <sam0x17> all of my masters thesis research was on efficient tree and graph indexing stuff
<FromGitter> <meltheadorable> you can model a lot of that stuff in a relational DB, but you can capture a lot more relationships in a graph, including character relationships
<FromGitter> <sam0x17> and I'm sitting on several patentable algorithms no one knows about because no one noticed it
<FromGitter> <meltheadorable> lol
<FromGitter> <meltheadorable> and arguably goodreads is a social network
<FromGitter> <tenebrousedge> patentable algorithm? that's a hard sell
<FromGitter> <meltheadorable> but when you start thinking about things in those terms you realize most useful apps are ;)
<FromGitter> <sam0x17> I don't believe in software patents, but it's rarely a hard sell unfortunately
<FromGitter> <sam0x17> should be nearly impossible
<FromGitter> <sam0x17> but isnt
<FromGitter> <tenebrousedge> it's harder than it used to be
<FromGitter> <meltheadorable> i actually think a graph DB is less useful for something like twitter, except to the extent you wanna fully creep out on recommendations , but the user-facing functionality of the app isn’t particularly well-served by graphs and it doesn’t support any real graph-style navigation
<FromGitter> <sam0x17> that's nice to hear at least
<FromGitter> <meltheadorable> but many apps are well-served if you can produce highly-interconnected data
<FromGitter> <meltheadorable> and that’s hard in a relational db
<FromGitter> <meltheadorable> how much of the graph functionality you want to expose is a kind of different question
<FromGitter> <meltheadorable> graph dbs are promising for a few things i want to build though
<FromGitter> <meltheadorable> but i ended up having to build a relational DB with a graph layer on top
<FromGitter> <meltheadorable> because graph databases are hard to use as the primary functional driver for an app
<FromGitter> <meltheadorable> in the frameworks that are developed now
<FromGitter> <meltheadorable> without taking on a lot of extra work i can’t really take on as a single-person team
<FromGitter> <sam0x17> but yeah, long story short, if you want an indexing data structure that will give you very nearly O(1) access to "all the descendants of node A that are of type B", and can be updated with node additions and subtractions efficiently, my data structure has got you covered: https://cs.brown.edu/research/pubs/theses/masters/2017/kelly.samuel.pdf
<FromGitter> <sam0x17> so in other words, if you want to make almost all DOM filter queries fast af, use my thing
<FromGitter> <meltheadorable> i also want a graph database that isn’t java or a triple store
<FromGitter> <meltheadorable> that is apparently too much to ask 😂
<FromGitter> <sam0x17> yes
<FromGitter> <sam0x17> lol
ht_ has joined #crystal-lang
dwdv has joined #crystal-lang
dwdv has quit [Ping timeout: 265 seconds]
ht_ has quit [Remote host closed the connection]
absolutejam2 has joined #crystal-lang
<FromGitter> <absolutejam_gitlab> @meltheadorable lighthouse, which is a graphql lib for Laravel has auth directives
<FromGitter> <absolutejam_gitlab> it's a pretty nice implementation
<FromGitter> <absolutejam_gitlab> but ultimately it's an API above your DB layer so auth should be perfectly doable
<FromGitter> <absolutejam_gitlab> https://github.com/ziprandom/graphql-crystal looks nice but it's early. Would be nice to have a solid GraphQL implementation
<FromGitter> <absolutejam_gitlab> > and lately i’m a little more inspired by things like phoenix liveview which uses dom diffing and websockets to allow writing the frontend in the backend, basically ⏎ ⏎ I've written a super basic LV app for log tailing and collating Sentry projects at work and I love it. I completely skipped any awful frontend work and it just works
<FromGitter> <absolutejam_gitlab> *really* like LV
absolutejam2 has quit [Ping timeout: 265 seconds]
<FromGitter> <spTorin> There is a simple XML document with a set of fields of the same type. How to properly iterate it? ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ Now `persons` is `XML::NodeSet`. If I try iterate it with `persons.each` - got error. [https://gitter.im/crystal-lang/crystal?at=5daff7fe10bd4128a1466416]
<FromGitter> <spTorin> ```code paste, see link```
absolutejam2 has joined #crystal-lang
<FromGitter> <absolutejam_gitlab> I'm not sure how the XML module works but most of the deserializers use a union type, and in this case it's treating `person` as a union of `Bool | Float64 | String | XML::NodeSet`
<FromGitter> <absolutejam_gitlab> What you need to do is add a guard clause that checks for that type
<FromGitter> <absolutejam_gitlab> then the compiler will be satisfied
<FromGitter> <absolutejam_gitlab> eg. ⏎ ⏎ ```persons = doc.xpath("//xml/person") ⏎ if persons.is_a? XML::NodeSet ⏎ person.each ...``` [https://gitter.im/crystal-lang/crystal?at=5dafff1b7477946badb44ce3]
<FromGitter> <absolutejam_gitlab> I assume that `XML::NodeSet` is something you can iterate
<FromGitter> <absolutejam_gitlab> Yeah you can
<FromGitter> <absolutejam_gitlab> Alternate ways of doing it are ⏎ ⏎ ```person = doc.xpath("//xml/person").as(XML::NodeSet)``` [https://gitter.im/crystal-lang/crystal?at=5dafff709c398215096b70f7]
<FromGitter> <absolutejam_gitlab> the latter will cast it to `XML::NodeSet` explicitly, but this will raise a runtime error if that isn't the right type
DTZUZO has quit [Ping timeout: 252 seconds]
dwdv has joined #crystal-lang
<FromGitter> <spTorin> I see, tnx! `.as(XML::NodeSet)` works good.
absolutejam2 has quit [Ping timeout: 265 seconds]
absolutejam2 has joined #crystal-lang
alexherbo2 has joined #crystal-lang
absolutejam2 has quit [Ping timeout: 246 seconds]
absolutejam2 has joined #crystal-lang
FromGitter has quit [Remote host closed the connection]
FromGitter has joined #crystal-lang
alexherbo22 has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 268 seconds]
<FromGitter> <ImAHopelessDev_gitlab> Good morning
<FromGitter> <ImAHopelessDev_gitlab> If you are in the east coast
absolutejam2 has quit [Ping timeout: 240 seconds]
absolutejam2 has joined #crystal-lang
<FromGitter> <absolutejam_gitlab> I'm on the East coast of England :shrug:
<FromGitter> <vlazar> > my data structure has got you covered: https://cs.brown.edu/research/pubs/theses/masters/2017/kelly.samuel.pdf ⏎ so in other words, if you want to make almost all DOM filter queries fast af, use my thing ⏎ ⏎ One have to build your data structure first to make DOM filter queries fast, right? Do you know if/when it would worth it to run a single DOM filter query? [ht
<FromGitter> ... tps://gitter.im/crystal-lang/crystal?at=5db0302b7477946badb5c390]
DTZUZO has joined #crystal-lang
alexherbo22 has quit [Ping timeout: 252 seconds]
alexherbo22 has joined #crystal-lang
DTZUZO has quit [Ping timeout: 265 seconds]
<FromGitter> <ImAHopelessDev_gitlab> I LOVE `.select`
<FromGitter> <bararchy> yeha
<FromGitter> <bararchy> select is great
<FromGitter> <bararchy> I really love `.find`
<FromGitter> <sam0x17> @vlazar you can incrementally update it as the DOM changes
sorcus has quit [Ping timeout: 276 seconds]
<FromGitter> <ImAHopelessDev_gitlab> WOW! Hi @bararchy long time no seeeeeeee!!
<FromGitter> <bararchy> Hi @ImAHopelessDev_gitlab I'm still waiting for Beta access to your game
sorcus has joined #crystal-lang
<FromGitter> <bararchy> There is something i'm not so clear about in regard to Mutex, what's the point of initializing it? ⏎ why not initialize some Global Mutex for every crtystal program and allow for something like ⏎ lock do ⏎ inside mutex context ⏎ end [https://gitter.im/crystal-lang/crystal?at=5db042122f8a034357c18751]
flaviodesousa has quit [Quit: KVIrc 4.9.3 Aria http://www.kvirc.net/]
DTZUZO has joined #crystal-lang
<FromGitter> <vlazar> lol, Global Mutex sounds like Global Interpreter Lock in Ruby ;)
<FromGitter> <mavu> My guess is that this allows for optimizations?
<FromGitter> <mavu> you can have a lock shared by 2 threads, but others can run freely whatever the state of the lock.
<FromGitter> <vlazar> does `Mutex.new` call is always close to `lock do ... end` call?
duane has quit [Ping timeout: 268 seconds]
<FromGitter> <bararchy> @vlazar the Mutex only locks what's in the do ... end, not the whole program
<FromGitter> <bararchy> it feels stupid to initialize it, instead of using it where needed as a macro or something
sorcus has quit [Ping timeout: 252 seconds]
<FromGitter> <sam0x17> @vlazar also of interest with respect to using my thing for dom queries is this: https://github.com/sam0x17/hierarch_old/blob/master/empirical_study/README.md
duane has joined #crystal-lang
Nekka_ has joined #crystal-lang
Nekka has quit [Ping timeout: 276 seconds]
Nekka_ is now known as Nekka
absolutejam2 has quit [Ping timeout: 240 seconds]
absolutejam2 has joined #crystal-lang
alexherbo22 has quit [Ping timeout: 265 seconds]
alexherbo22 has joined #crystal-lang
duane has quit [Ping timeout: 265 seconds]
alexherbo22 is now known as alexherbo2
duane has joined #crystal-lang
ht__ has joined #crystal-lang
HumanGeek has joined #crystal-lang
HumanGeek has quit [Remote host closed the connection]
absolutejam2 has quit [Ping timeout: 246 seconds]
HumanGeek has joined #crystal-lang
hightower4 has joined #crystal-lang
Human_G33k has quit [Ping timeout: 240 seconds]
ua has quit [Ping timeout: 265 seconds]
Nekka has quit [Ping timeout: 264 seconds]
Nekka has joined #crystal-lang
duane has quit [Ping timeout: 240 seconds]
ua has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 252 seconds]
<FromGitter> <ilanpillemer> what is a `record`?
<FromGitter> <tenebrousedge> a struct
<FromGitter> <tenebrousedge> `record` is a macro that creates a struct
<FromGitter> <ilanpillemer> no difference?
<hightower4> Hm, I want to have "getter mything : SomeClass". But SomeClass must be called as SomeClass.new(self), basically I want to initialize it with a pointer to object containing it. Now my issue is, I can't do "getter mything = SomeClass.new(self)" because self is not defined in this context. But it also appears I can't do "@mything = SomeClass.new(self)" in initialize() because then the automatic type I get is "SomeClass | Nil", instead of
<hightower4> "SomeClass" that I wanted. How do I solve this?
<FromGitter> <ilanpillemer> where is the doc on that? In macros?
<FromGitter> <ilanpillemer> hmm.. I cant see anything here https://crystal-lang.org/reference/syntax_and_semantics/macros.html
<FromGitter> <ilanpillemer> where can I find out more about record?
<FromGitter> <tenebrousedge> hightower, can you stick an example here (https://play.crystal-lang.org/) ?
<FromGitter> <tenebrousedge> @ilanpillemer here (https://crystal-lang.org/api/0.31.1/toplevel.html#record(name,*properties)-macro)
<FromGitter> <tenebrousedge> ugh
<FromGitter> <tenebrousedge> https://crystal-lang.org/api/0.31.1/toplevel.html#record(name,*properties)-macro
<FromGitter> <straight-shoota> hightower4: You can use a lazy getter: `getter mything { SomeClass.new(self) }`. The block will be executed the first time the getter is called.
<FromGitter> <ilanpillemer> Thanks!
<hightower4> straight-shoota oh, oh that'd work, thanks
duane has joined #crystal-lang
<FromGitter> <ilanpillemer> oh.. that is so nice
<FromGitter> <ilanpillemer> immutable data structs
<FromGitter> <tenebrousedge> yis
<FromGitter> <tenebrousedge> just don't make them super large, probably not efficient
<hightower4> straight-shoota actually, would it? Why doesn't this work: https://play.crystal-lang.org/#/r/7v0h
<FromGitter> <Blacksmoke16> because thats a proc
<hightower4> Well I tried just with {} as advised, but same error
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7v0m
<hightower4> ah interesting, didn't know about this syntax
<hightower4> ok thanks
<FromGitter> <ImAHopelessDev_gitlab> hi
<FromGitter> <Blacksmoke16> are the docs on it
<hightower4> Blacksmoke16 where is that from?
<FromGitter> <tenebrousedge> hightower: https://crystal-lang.org/api/0.31.1/Object.html#property(*names,&block)-macro
<FromGitter> <Blacksmoke16> the getter one but yea
<hightower4> ah.. ok, thanks
<FromGitter> <JohnDowson> Has anyone managed to make Scry do anything useful in Vim?
duane has quit [Ping timeout: 252 seconds]
<hightower4> Uhm, how do I alias a method?
<FromGitter> <Blacksmoke16> like on a type that you control?
<hightower4> yes, just want 2 methods to be the same
<FromGitter> <ilanpillemer> what does `||=` do?
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5db087c710bd4128a14ab1bc]
<FromGitter> <Blacksmoke16> is like `or equal`
<FromGitter> <tenebrousedge> there should be an `alias_method`
<FromGitter> <Blacksmoke16> i.e. if there isn't already a value, assign it
<hightower4> yeah I was recalling alias_method, but can't find it now
<FromGitter> <Blacksmoke16> its not a thing
<hightower4> ilanpillemer 'x||=y' means 'x = x || y
<hightower4> Same thing can be done with any other operator, like +, -, etc.
<FromGitter> <Blacksmoke16> @ilanpillemer https://play.crystal-lang.org/#/r/7v15
<hightower4> ok thanks blacksmoke, I must remember it from ruby then
<FromGitter> <Blacksmoke16> is helpful in a hash for example as you could do like `(hash[key] ||= Array(Int32).new) << value`
absolutejam2 has joined #crystal-lang
<FromGitter> <Blacksmoke16> i.e. if that key doesn't exist yet, initialize it to an empty array, otherwise push the value
<FromGitter> <tenebrousedge> apparently there used to be an `alias_method` but it was removed https://github.com/crystal-lang/crystal/pull/1966
<FromGitter> <tenebrousedge> if I'm reading that right
duane has joined #crystal-lang
<FromGitter> <tenebrousedge> @Blacksmoke16 why would you not just set a default block for the hash?
<FromGitter> <absolutejam_gitlab> That proc getter is sweet
<FromGitter> <absolutejam_gitlab> didn't know about that
<FromGitter> <Blacksmoke16> @tenebrousedge hm?
<FromGitter> <tenebrousedge> `a = Hash.new { |h,k| h[k] = Array(Int32).new) }; a << value `
<FromGitter> <Blacksmoke16> because if the key is encountered again you dont want to reset its value to an empty array
<FromGitter> <tenebrousedge> it wouldn't be
<FromGitter> <tenebrousedge> it's a default block
<FromGitter> <tenebrousedge> it's only invoked if the key doesn't exist
<FromGitter> <Blacksmoke16> ah fair enough
<FromGitter> <Blacksmoke16> in that case because the hash could be a return value from something else? :shrug: was just an example :P
<FromGitter> <absolutejam_gitlab> Anyone used Storybook or Styleguidist?
<FromGitter> <absolutejam_gitlab> Storybook looks neat
<FromGitter> <absolutejam_gitlab> or anything in that vein
<hightower4> Hey I notice that I can define a function with "def x" without having to add empty parentheses at the end like "def x()". Was this relatively recently added or I don't remember that it was always like this?
<FromGitter> <tenebrousedge> always like that
<FromGitter> <tenebrousedge> same in Ruby
<hightower4> ah maybe then I am remembering that if arguments are given, then they must be inside (), unlike ruby where they don't have to be
<hightower4> (i.e. "def x a, b, c" is valid ruby, but not crystal)
absolutejam2 has quit [Ping timeout: 276 seconds]
<FromGitter> <asterite> yeah, we removed that syntax because def foo x : Int32 is ambiguous (is is the return type or the argument type?)
<FromGitter> <meltheadorable> no-parens style for ruby methods with arguments was a henious crime against humanity anyway
Nekka has quit [Ping timeout: 268 seconds]
<FromGitter> <tenebrousedge> word
return0e_ has joined #crystal-lang
return0e has quit [Ping timeout: 268 seconds]
dannyAAM has quit [Quit: znc.saru.moe : ZNC 1.6.2 - http://znc.in]
dannyAAM has joined #crystal-lang
<FromGitter> <asterite> lol
<hightower4> Hey tell me... let's say I have a method like 'def something(myproc) somethingelse(myproc) end'. This method works with any type. Now, inside something(), I would like to wrap myproc into a new proc of exactly the same signature, and then call somethingelse(newproc). Can I do this without explicitly specifying type?
<FromGitter> <tenebrousedge> procs can use generics
<hightower4> yes, but if that's the only way to go, how would I apply this to this case?
<FromGitter> <tenebrousedge> what are you trying to do, more generally?
<FromGitter> <Blacksmoke16> or better yet, got an example
<FromGitter> <tenebrousedge> (we like when people use https://play.crystal-lang.org/ to show us things)
<hightower4> If I tell you I'm gonna open a can of worms here... it's something I've been trying to do for more than a year... I want to port blessed (https://github.com/chjj/blessed) to crystal. And I got very far with it, but the one component I haven't been able to convert is the event system, contained in blessed's file lib/events.js.
<hightower4> So basically, if you're asking what I'm trying to do, the answer is - port/mimick functionality of lib/events.js in crystal
<FromGitter> <Blacksmoke16> we mean more so like a simplified example of the issue you're running into
<hightower4> I know, but I'm not sure I can provide that, since it's very contextual
<hightower4> The description I gave above is the most simple I could provide -- I want to wrap a proc into another proc, of the same type/signature, to add a couple additional lines around the original one
<hightower4> But I seem to not be able to do this because it requires me to specify types, which, if I don't touch the proc, I don't have to and it just works
<FromGitter> <absolutejam_twitter> Unrelated to Crystal
<FromGitter> <absolutejam_twitter> But this is a sweet pattern for Go https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
<FromGitter> <Blacksmoke16> yea without a visual example im not sure
<hightower4> yeah, will probably need to make another attempt with generics, not sure
<hightower4> ok, thanks for the discussion
<hightower4> fg
<FromGitter> <tenebrousedge> hightower, can the inner method take a block instead of a proc?
<hightower4> yes
<FromGitter> <absolutejam_gitlab> hightower4: port that and I'll marry you
<FromGitter> <tenebrousedge> You could pass a block and inside it do your extra stuff and block.call
<hightower4> yes I've been thinking about this for over a year... got almost all converted, except for the contents of lib/events.js. Tried numerous approaches, couldn't figure it out yet
hightower4 has left #crystal-lang ["Leaving"]
hightower4 has joined #crystal-lang
absolutejam2 has joined #crystal-lang
<hightower4> tenebrousedge hm, potentially, I don't have all the implications of this in mind, could eventually just do a dumb try to see if it works
<hightower4> tenebrousedge eh not gonna work, since as mentioned the input arguments need to be the same as to a proc, which requires me to somehow know them, and in this approach without using generics I don't
<hightower4> but I have something in mind... that executes the line I want outside of the proc, so I don't have to touch it
<FromGitter> <absolutejam_twitter> Can you give a pseudocode example?
<FromGitter> <absolutejam_twitter> Or Ruby lol
absolutejam2 has quit [Ping timeout: 276 seconds]
<hightower4> eh if it was ruby the translation would be trivial :)
<FromGitter> <absolutejam_twitter> Because it seems like what you wanna do would be doable but maybe not in the exact way
absolutejam2 has joined #crystal-lang
<hightower4> yeah the data structure in js is basically events = { string_name = [ array of procs ] }. But, since all events are known in advance, what I did is turn 'events' into a class, and each 'string name' is a separate variable whose value is then [] of known type (procs that accept and return arguments specific for this event)
<hightower4> that's the basic of how I tried to convert it in this latest/most recent attempt
<FromGitter> <Blacksmoke16> do all the procs have the same args?
<hightower4> they all return Bool, but what they are called with (input arguments) vary. What I did is I have identified common types (since some events take same arguments), and then each event inherits from that reduced set of different types
<hightower4> Like, all mouse-related events get called with (buttons, modifiers, x, y)
<FromGitter> <Blacksmoke16> got an example of the syntax you would like for how to register these?
<hightower4> Yes. In js they do it like they'd do it in ruby, which is basically addListener( 'mousedown', myproc ), and then later the code just calls listeners.each do myproc('mousedown', whatever args...) .
<hightower4> Since we can't do this directly in crystal, what I did was turn this into:
<hightower4> self.events.mousedown.addListener( myproc ), and the input/output args of myproc are known in advance.
<hightower4> (and this part works so far even without generics or macros)
<hightower4> But I think this barely escapes the question of types, and I'll need to switch to generics to get some more options available
<FromGitter> <Blacksmoke16> sec
<FromGitter> <tenebrousedge> so your function is getting a proc, and you need to wrap it how exactly?
<hightower4> tenebrousedge the "edge" case which currently doesn't work (not even in this limited prototype) is that in addition to registering an event handler, you can request it to run only once and then be deleted. So my idea was to, if the code requests one-time trigger, to wrap the original proc into another one which runs it once, and then deletes itself
<hightower4> (which is also how js code does it)
<FromGitter> <absolutejam_twitter> Why not wrap the procs in a class/struct?
<hightower4> mm, have an example of this, even if just pseudo code?
<FromGitter> <absolutejam_twitter> It doesn't have to be a 1for1 translation, just wrap them in a class and give it a call method, a called property, etc.
<hightower4> aah, that's not a bad idea
<hightower4> although what difference/flexibility would it make compared to existing procs?
<hightower4> s/make/give/
duane has quit [Ping timeout: 276 seconds]
<FromGitter> <absolutejam_twitter> Well you can just do more with a class. Or even use an interface and have many different class definitions if you have to handle different arguments
<hightower4> ok I'll think about this, it's not a bad suggestion
<FromGitter> <absolutejam_twitter> Or use a decorator pattern, a proc that returns a proc
<FromGitter> <absolutejam_twitter> But that's a bit less straight forward and less extensible
<FromGitter> <tenebrousedge> that is something that occurred to me, but types sound like they would still be a problem
<FromGitter> <Blacksmoke16> what executes these events?
<hightower4> yes, at first sight seems like it would still be an issue
<FromGitter> <Blacksmoke16> like is that something the user can call on their own or?
<hightower4> blacksmoke16: in js it's manual invocation, the code does object.emit('event name', any args...). In my case with the described scheme of events.<name>, I emit using events.<name>.emit(known arg types)
<hightower4> (and the emit basically just iterates over stored procs and calls them with the given args... )
<FromGitter> <Blacksmoke16> and im assuming the given args are required/specific to each type of event
<FromGitter> <Blacksmoke16> i.e. would error if you pass the wrong args its not expecting?
<FromGitter> <Blacksmoke16> pass args it's not expecting, or not enough etc?
<hightower4> in general the js code doesn't check all args for validity, it just assumes the caller knew what they had to pass
<FromGitter> <Blacksmoke16> ok
<hightower4> but yes, they're specific for each call
<FromGitter> <absolutejam_gitlab> distinct types then?
<hightower4> basically I have identified groups of events. Some receive no inputs, some receive one string, some receive set of keys and modifiers, some receive mouse status like (buttons, modifiers, x, y), and so on.
<hightower4> So I turned each of those into a class
<hightower4> (each of distinct input arguments I mean)
<hightower4> and then I say e.g.:
<hightower4> getter event_mousedown : ArrayMouseCoords = ArrayMouseCoords.new
<hightower4> And so calling events.event_mousedown then knows what it is and what it accepts etc.
<hightower4> (it's defined as Array of Procs, each Proc e.g. accepting (btns, mods, x, y) as arguments and returning Bool
<hightower4> whereas some event like 'redraw' which takes no arguments is currently defined as:
<hightower4> getter redraw : ArrayNone = ArrayNone.new , and it accepts array of Procs which just return bool, with no input args
<hightower4> and also of course they have their own emit() methods. The events.mousedown.emit() takes 4 args, while events.redraw.emit() takes none, etc.
<FromGitter> <absolutejam_gitlab> Why not make it clear and have `type RedrawEmit`?
<FromGitter> <absolutejam_gitlab> fuck, deleted my message
<FromGitter> <absolutejam_gitlab> why not make it clear and have type `RedrawEmit`?
<hightower4> Well, same thing, also doable. My idea was to "compress" into as few types as needed, like, all events taking no input args would just have type "None" rather than their own specific type
<hightower4> but yes, both approaches would work... this part is not the crux of the issue
<FromGitter> <sam0x17> ooooh what's the GUI framework being discussed ^
<hightower4> sam0x17: my attempt to port https://github.com/chjj/blessed to crystal
<hightower4> sam0x17: got trouble porting file lib/events.js; the rest I made a lot of progress with
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7v5b
<FromGitter> <Blacksmoke16> idk is what i came up with
duane has joined #crystal-lang
<hightower4> mm, looks interesting let me ponder on it
<FromGitter> <tenebrousedge> yeah, the `*args` requirement seems like it demands a macro
<FromGitter> <Blacksmoke16> i was just thinking
<FromGitter> <Blacksmoke16> if all events are just going to be `Proc(EventType, Bool)`
<FromGitter> <Blacksmoke16> it can be a singular arg
<FromGitter> <Blacksmoke16> where that arg wraps the possible args, like my records for example
<hightower4> Like a union of types? Wouldn't it allow someone to call with incorrect args? (E.g. to call function taking 4 args with 0 or 1 args intended for some other function)
<FromGitter> <Blacksmoke16> im thinking no
<FromGitter> <Blacksmoke16> `Dispatcher.emit Other, Other.new(1), "foo"` => `Error: no overload matches 'Proc(Other, Bool)#call' with types Other, String`
<hightower4> What's the trick with passing class/struct as first arg to emit(), I don't see it used inside the generated function?
<FromGitter> <Blacksmoke16> you're just wrapping the args related to an eventType within its own type
<FromGitter> <Blacksmoke16> like in JS how would a mouse Event look like `emit('mouse', {button: "x", ...});` something like that?
<FromGitter> <Blacksmoke16> or like `emit('mouse', "x", true, false, 123, ...);`?
<hightower4> like the latter one
<FromGitter> <Blacksmoke16> and the handler would be setup like `function(button, up, down, id, ...)`?
<hightower4> yes
<FromGitter> <Blacksmoke16> sec
<hightower4> or even *args in some cases, since it allows full freedom like ruby would do it
absolutejam2 has quit [Ping timeout: 240 seconds]
<hightower4> Blacksmoke16 but it's not relevant to map their logic 1:1, whatever works and/or is "best" is OK
<hightower4> the more important question is,
<hightower4> how would your solution be modified to work on objects? Each object has its own events, so the pseudo code would be like:
<hightower4> button = Button.new
absolutejam2 has joined #crystal-lang
<hightower4> button.events.clicked.addListener(myfunc)
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7v5r
<hightower4> button.events.clicked.emit( [...], [...], x, y)
<FromGitter> <Blacksmoke16> something like that then?
<FromGitter> <Blacksmoke16> also get compile time safety if you were to do like `Dispatcher.emit Mouse, 1, true, false`
<FromGitter> <Blacksmoke16> `Error: no overload matches 'Proc(String, Bool, Bool, Bool)#call' with types Int32, Bool, Bool`
<hightower4> yes, hehe nice
<FromGitter> <didactic-drunk> Should this be an append instead of an `IndexError` ⏎ ⏎ ```ary = Array(X).new ⏎ ary[0] = x``` [https://gitter.im/crystal-lang/crystal?at=5db0b3b62a6494729c28f96b]
<hightower4> Blacksmoke16 this looks really nice, thanks
<FromGitter> <absolutejam_twitter> Why is it erroring at all?
<hightower4> I'm gonna try incorporate it
<FromGitter> <Blacksmoke16> 💭
<FromGitter> <Blacksmoke16> 👍
<jhass> didactic-drunk: intentional semantic difference from ruby. The problem is what if you do `a = [] of String; a[99] = 'foo'; a[5]`, what would that return?
<hightower4> Blacksmoke16 another interesting challenge in this area is that in addition to specific events, they also have an event called "event", which is emitted with the name of real event along with any args. Meaning, if we emit(Mouse, 1,2,3,4), then the code also emits(Event, Mouse, 1,2,3,4). This does not appear critical for porting as it is almost unused, but if you have an idea how to handle that, that'd be awesome
<FromGitter> <absolutejam_gitlab> js is a mess
<hightower4> yes, yes, no question about that. But the same would work in Ruby with no issue as well
<FromGitter> <didactic-drunk> @jhass that doesn't really count when the size increments by 1. The current behavior broke my sequential array append using ```obj = ary[i] ||= foo```
<jhass> but it'd be inconsistent to allow it for .size + 1 but not for .size + 2
<jhass> obj = (ary[i]? || ary << foo)
<FromGitter> <straight-shoota> @didactic-drunk I agree, it's a bit weird that you can't dynamically resize an array with `#[]=` and need to use `#push` or `#+` for that
<FromGitter> <straight-shoota> I've been bitten by this as well, wasn't expecting that behaviour
<FromGitter> <didactic-drunk> @jhass Doesn't `ary << foo` return `ary`?
<jhass> ah, true receiver not value
<jhass> mh, need a negative .try :D
<jhass> amazingly `obj = ary[i]? || (ary << foo; foo)` runs
<jhass> not entirely sure I like it yet :D
<FromGitter> <straight-shoota> no, not really nice
<FromGitter> <didactic-drunk> @jhass I don't see it as inconsistent. Uninitialized values are the reason `ary[99] = ` doesn't work. `@ary[size] = ` doesn't have that problem and could be treated as an append.
<FromGitter> <straight-shoota> maybe `Array#push` could be changed to return the value instead of the receiver?
<FromGitter> <didactic-drunk> @jhass I used `.tap`
dwdv has quit [Ping timeout: 240 seconds]
<jhass> I guess that would make it inconsistent with `#<<`
<FromGitter> <straight-shoota> @didactic-drunk True. `ary[ary.size - 1] = x` works, so from a consistency stance it's not a big difference whether `@ary[ary.size] = x` fails or not. But it would be convenient.
<jhass> well for `ary[ary.size] ||= x` to work `[]` would need to return `nil`
<FromGitter> <tenebrousedge> what about `array.concat([val])` ?
<FromGitter> <straight-shoota> jhass, do `#<<` and `#push` need to be consistent? Currently, it's just an alias. But IDK maybe having a little bit different behaviour would be good for use cases like this?
<jhass> that's just .push/<<
<FromGitter> <tenebrousedge> I think I'm failing to see the point here
<jhass> I don't know, somehow it feels right to me that they're aliases. I wouldn't mind toooo much for `#push` to go even
<jhass> maybe we could make `obj = ary[i]? ||= foo` work, even for `i = ary.size`
<jhass> but that involves a parser change
<FromGitter> <christopherzimmerman> I've been looking through the docs for type inference, is there a short way to tell if a type if a Union?
<jhass> and an new special method, `[]?=`
<FromGitter> <Blacksmoke16> hightower4: im assuming that contains like metadata common to all events?
<FromGitter> <Blacksmoke16> or what exactly does that represent?
<FromGitter> <straight-shoota> Doesn't `ary[i] ||= x` expand to `ary[i]? || (ary[i] = x)`?
<FromGitter> <didactic-drunk> @jhass I see the rubyisms don't translate perfectly especially when nil is considered.
<jhass> no it doesn't (to both :D)
<hightower4> Blacksmoke16 well it represents an event called "event", which can basically replay/listen on all other events. So if you register a block for "event", then you get notified of all events being triggered, and the args you receive are (original event, original event's args)
<FromGitter> <didactic-drunk> ```ary.get(i) { new_value }```?
<jhass> chris: at compile time, runtime or just for inspection?
<hightower4> Blacksmoke16 btw I converted your code to work on objects with no issues, ++
<FromGitter> <straight-shoota> > Doesn't `ary[i] ||= x` expand to `ary[i]? || (ary[i] = x)`? ⏎ ⏎ Yes, it does. So it should work perfectly fine if `ary[ary.size] = x` is accepted.
<jhass> oh, sorry I misread
<hightower4> Blacksmoke16 And another related issue is how would this model be adapted to be able to have not only add() but also add_once(). Add_once() would add a handler as usual, but automatically delete it after it was once triggered
<FromGitter> <Blacksmoke16> uhh
<FromGitter> <Blacksmoke16> :shrug:
ht__ has quit [Quit: ht__]
<FromGitter> <tenebrousedge> things generally can't delete themselves
<FromGitter> <tenebrousedge> you would presumably have to trigger a deletion action and pass `self`
absolutejam2 has quit [Ping timeout: 268 seconds]
absolutejam2 has joined #crystal-lang
<FromGitter> <repromancer_gitlab> speaking of arrays and Ruby, is there a Crystal equivalent to the Ruby `Array#reduce(symbol)` shorthand? For example: ⏎ ⏎ ```[1] pry(main)> [1,2,3,4].reduce(:*) ⏎ 24``` ⏎ ⏎ I know there is `Array#product`, but I'm wondering if I can explicitly say "I want to reduce this array using this function". [https://gitter.im/crystal-lang/crystal?at=5db0bfa7a3f0b178497812dd]
<jhass> yes, we sticked to the inject name
<FromGitter> <repromancer_gitlab> (where the function would be passed in by name or value, and would be assumed to take the accumulator and element)
<jhass> and didn't add the reduce alias
<FromGitter> <tenebrousedge> not really. Ruby special-cases a few methods to work `reduce`
<jhass> like whose?
<FromGitter> <tenebrousedge> you can't pass arbitrary symbols to Ruby's `reduce` and expect correct behavior
<FromGitter> <repromancer_gitlab> Oh, that makes me less jealous.
<FromGitter> <Blacksmoke16> @repromancer_gitlab `[1,2,3,4].product # => 24`
<FromGitter> <Blacksmoke16> 😉
<FromGitter> <Blacksmoke16> oh and the docs are broken on master
<FromGitter> <straight-shoota> jhass, @didactic-drunk see #8370 =)
<DeBot> https://github.com/crystal-lang/crystal/issues/8370 (Array: Let #[]= append an element to the end of the array)
<jhass> https://carc.in/#/r/7v6l so this is incorrect behavior? how?
<FromGitter> <repromancer_gitlab> @Blacksmoke16 Yeah, I found that, but was looking for a way to pass in an arbitrary function, which is what I thought Ruby was allowing.
<FromGitter> <Blacksmoke16> https://crystal-lang.org/api/master/Enumerable.html#(pattern)-instance-method
<FromGitter> <Blacksmoke16> all methods dont have a name
<FromGitter> <straight-shoota> ooops
<FromGitter> <straight-shoota> In the summary there are names, but stripped of a few characters at the beginning
<FromGitter> <Blacksmoke16> 😬
<FromGitter> <didactic-drunk> @straight-shoota I don't know if you saw my most recent comment in #8355. `same_file?` returns false positives without #8355.
<DeBot> https://github.com/crystal-lang/crystal/pull/8355 (Provide access to 64 bit inode numbers.) | https://github.com/crystal-lang/crystal/pull/8355 (Provide access to 64 bit inode numbers.)
<FromGitter> <straight-shoota> @didactic-drunk No, haven't looked into that yet
<FromGitter> <straight-shoota> @Blacksmoke16 I have no idea how this error could possibly be happening
<FromGitter> <straight-shoota> The only relevant recent change to method names in the doc generator was https://github.com/crystal-lang/crystal/commit/13c7c5504ccd40385be12371c7030d5cae4a385c#diff-b04a18f501e2b67dce56e2f7202245d2R21-R28
<FromGitter> <straight-shoota> But that can't possibly produce such an (inconsitent) result
<hightower4> tenebrousedge yes, yes, I didn't mean delete the object, but just remove itself from the array of handlers, so on next invocation it is not there and therefore no longer triggered
dwdv has joined #crystal-lang
<hightower4> Uhm, why can't I define a method to take arg X, and then pass some subclass of X in its place? I have "record X < Event, event : Event.class", but then when I try passing SubclassOfEvent as argument, I get: Error: type must be Event+.class, not SubclassOfEvent.class
<FromGitter> <straight-shoota> Oh darn, I confused `String#lstrip` with `String#lchop` 😠
<FromGitter> <straight-shoota> Fix in #8371, thanks for reporting @Blacksmoke16
<DeBot> https://github.com/crystal-lang/crystal/pull/8371 (Fix method names incorrectly stripped in doc generator)
<FromGitter> <Blacksmoke16> 👍 nice!
<FromGitter> <Blacksmoke16> hightower4: i had an idea
<hightower4> would love to hear! :-)
<FromGitter> <Blacksmoke16> sec
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7v7k
<hightower4> haha, veery nice
<hightower4> You'd say reject() is faster than e.g. array.delete(handler) if handler.run_once ?
<FromGitter> <Blacksmoke16> its `reject!`, notice the `!`
<hightower4> yes, yes, I did
<hightower4> great
<FromGitter> <Blacksmoke16> id imagine it would be a bit faster? you'd have to benchmark it
alexherbo2 has joined #crystal-lang
<hightower4> If you're up for another issue on this topic.. :) When a new listener is added, like, if we call Dispatcher.add(Other, &block), then in addition to of course adding the handler, the system should also emit event called NewListener, with 2 arguments, one being the event class/struct, and the other being block itself
<FromGitter> <Blacksmoke16> oh so like an event when an event is registered?
<hightower4> yes
<hightower4> I tried to make this addition but was unsuccessful
<hightower4> I couldn't pass any arguments to it (nor struct nor block)
<FromGitter> <Blacksmoke16> the block itself? how would that work in js?
<FromGitter> <Blacksmoke16> how would having that be useful?
<hightower4> For how it works in js, simple because they can pass functions around.. so if they call add('mouse', myhandler), then the add() function can easily call emit('newListener', 'mouse', myhandler)
<FromGitter> <Blacksmoke16> right, but whats the usecase that a newEvent listener would need the function?
<hightower4> You mean why it would need to be passed a block? This is called 7 times in the original code, let me look up whether they do anything with the block or just ignore it
<FromGitter> <Blacksmoke16> 👍
<FromGitter> <Blacksmoke16> idk what they would do with it, wouldnt make sense to execute it
<FromGitter> <Blacksmoke16> and its not like you can do much more besides save it somewhere or run it
<hightower4> yeah one reason why they'd keep it is because when you call removeListener, you remove it by passing that block/function
<hightower4> like if you call add('mouse', myhandler), the way to remove it is remove('mouse',myhandler)
<FromGitter> <Blacksmoke16> ah ok yea, that makes sense
<hightower4> (but let me check whether they use it like this or not in this specific case of listening on NewListener)
<hightower4> yeah, they do
<hightower4> actually no, they don't, they always ignore the block/function
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7v7v theres remove functionality
<hightower4> (although theoretically the above example with remove stands, because that's exactly what they do -- remove something when they get notified via NewListener; it's just that the thing they remove is some other block, and not that block which was just added)
<FromGitter> <Blacksmoke16> cant use the block form for that tho
<FromGitter> <Blacksmoke16> so would have to use an explicit proc
<FromGitter> <Blacksmoke16> prob could make some private method to lean up that logic, sec
<hightower4> ah yes, I came up with this myself too. Btw, is there a way to convert event arguments (like that "id : Int32" into a type), so that a type name could be used both there and when manually creating a proc?
<hightower4> This would simplify it a lot, as one wouldn't have to copy all args to create a proc
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7v80
<FromGitter> <Blacksmoke16> uhh hmm
<FromGitter> <ilanpillemer> how would you do this?
<FromGitter> <ilanpillemer> ``` property f1, f2, f3, f4 = [] of String```
<FromGitter> <ilanpillemer> in a way that works?
<FromGitter> <ilanpillemer> I want to create a bunch of properties with the same type
absolutejam2 has quit [Ping timeout: 268 seconds]
<hightower4> ilanpillemer I'm not aware of a way to assign the same type to a list of variables, maybe someone else would know. A macro could surely help if one doesn't exist already, or if you end up doing it manually, you could create an alias for your type, to have it be shorter (e.g. if you alias AS = Array(String), then you can use AS for type)
<FromGitter> <Blacksmoke16> hightower4: yes, sec
<hightower4> Blacksmoke16 I've checked that events.js and basically these 2 things remain: 1) This mentioned ability to call emit(NewListener, Event[, Block/Proc]) when something is added, 2) Ability to emit an event which receives the original event and all args. (E.g. if we call emit(Mouse, 1,2,3), then the system also emits event named Event with args (Mouse,1,2,3)
<FromGitter> <ilanpillemer> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5db0d93b2f8a034357c64574]
<FromGitter> <ilanpillemer> this just seems so unneccesary
Nekka has joined #crystal-lang
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7v9k am i missing something here?
<FromGitter> <Blacksmoke16> nvm
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7v9r
<FromGitter> <Blacksmoke16> hightower4: `Other::Handler.new { |id| pp "fancy"; false }`
<FromGitter> <Blacksmoke16> 😉
<hightower4> wonderful idea
<hightower4> implementation even more so :)
<FromGitter> <tenebrousedge> @ilanpillemer in your first code example, you can't distinguish between "a sequence of properties, of which the last is typed" and "a sequence of properties, all with the same type"
<FromGitter> <tenebrousedge> you can explicitly initialize the properties in the constructor if you like
<FromGitter> <Blacksmoke16> newListener should be doable
<FromGitter> <Blacksmoke16> well
<FromGitter> <Blacksmoke16> you cant have variable size procs so im not sure how that would work
<FromGitter> <tenebrousedge> you can do that with generics
<FromGitter> <tenebrousedge> but it may not work for what you're trying to do
<hightower4> Blacksmoke16 yeah, I'm playing with adapting the code right now and then trying to add newListener (although I failed on the first try, will revisit why). As for the variable size procs, how about packing the args into an array and sending it as 1 argument maybe?
<FromGitter> <Blacksmoke16> that would be doable
<FromGitter> <Blacksmoke16> imma go eat then will look into it more
<hightower4> awesome, thanks
dwdv has quit [Ping timeout: 265 seconds]
alexherbo2 has quit [Quit: The Lounge - https://thelounge.chat]