00:18:47 | * | brson quit (Ping timeout: 240 seconds) |
00:24:56 | ldlework | here is a very minimal version of the segfault, https://glot.io/snippets/eoo5a3fym9 |
00:27:04 | ldlework | more minimal https://glot.io/snippets/eoo5coc8vu |
00:30:34 | ldlework | more minimal and clarified, https://glot.io/snippets/eoo5fzadlo |
00:30:58 | zachcarter | hmmm |
00:31:00 | zachcarter | https://gist.github.com/zacharycarter/d2a42b5fd94c058d391c4653701e4b06 |
00:31:34 | zachcarter | I think this is kind of what I want to do |
00:31:37 | zachcarter | but not working |
00:32:23 | ldlework | as a gist, https://gist.github.com/dustinlacewell/90596e2bab75dbd872dd90058fc9762d |
00:41:52 | zachcarter | not sure you can do |
00:41:54 | zachcarter | T: concept |
00:41:57 | zachcarter | proc newParam[T](name: string, value: T): Parameter[T] = |
00:41:58 | zachcarter | result = Parameter[T](name:name, value:value) |
00:41:59 | zachcarter | compiles |
00:42:43 | ldlework | zachcarter: you can do T: concept, but where its random because its buggy as hell |
00:42:52 | zachcarter | ah |
00:43:44 | ldlework | zachcarter: if you take out the concept-constraint on the Parameter type decl, and keep it on the newParam procs, it works |
00:43:48 | ldlework | but not on both |
00:44:07 | zachcarter | hrm |
00:44:34 | ldlework | Well I think it just doesn't work on the type |
00:44:40 | zachcarter | yeah |
00:44:50 | ldlework | As soon as I constrain the type it segfaults or complains |
00:45:05 | ldlework | type mismatch: got (Parameter[system.int]) but expected 'Parameter[system.bool]' |
00:45:17 | ldlework | for the line: intParam = newParam[int]("count", 0, 0, -1) |
00:45:20 | ldlework | makes no sense |
00:45:49 | ldlework | it should expect Paramter[ValidType] |
00:45:54 | ldlework | which system.int is one of |
00:48:19 | * | smt_ joined #nim |
00:50:53 | * | smt quit (Ping timeout: 260 seconds) |
01:01:32 | ldlework | type mismatch: got (Parameter[system.bool]) but expected 'Parameter[]' |
01:01:43 | * | brson joined #nim |
01:01:51 | ldlework | the fuk does that even mean |
01:02:22 | Xe | it expeted a generic |
01:02:27 | Xe | withntype arg |
01:02:30 | Xe | wow |
01:02:33 | Xe | stupid hands |
01:02:47 | * | ftsf joined #nim |
01:12:26 | * | vendethiel quit (Ping timeout: 240 seconds) |
01:14:38 | * | vendethiel joined #nim |
01:15:33 | ldlework | just doing --reportConceptFailures:on makes my program fail |
01:15:43 | ldlework | lib/system.nim(2358, 24) Error: type mismatch: got (NimNodeKind) |
01:15:51 | ldlework | Nimmmmmmmmm |
01:18:17 | ldlework | think I'll come back in another 5 years :) |
01:30:50 | * | brson quit (Quit: leaving) |
01:35:46 | krux02 | ldlework: I remember to have problems like yours, too |
01:36:07 | krux02 | you should redefine your fucntion so that you can use it like this: |
01:36:36 | krux02 | newParam(int, "count", 0,0,-1) |
01:37:08 | krux02 | proc newParam[T](typ: typedesc[T]; ... ) |
01:41:04 | * | libman quit (Quit: Connection closed for inactivity) |
01:41:07 | * | krux02 quit (Remote host closed the connection) |
01:45:26 | * | Nobabs27 joined #nim |
02:08:47 | * | vivus quit (Quit: Leaving) |
02:10:55 | ftsf | good day! o/ |
03:00:23 | * | SusWombat_ quit (Remote host closed the connection) |
03:02:43 | * | smt_ quit (Ping timeout: 260 seconds) |
03:13:49 | * | vendethiel quit (Ping timeout: 258 seconds) |
03:15:30 | * | vendethiel joined #nim |
04:03:08 | * | zachcarter_ joined #nim |
04:07:31 | * | shashlick_ joined #nim |
04:10:44 | * | shashlick quit (*.net *.split) |
04:10:45 | * | zachcarter quit (*.net *.split) |
04:10:45 | * | zachcarter_ is now known as zachcarter |
04:15:57 | ldlework | hi ftsf |
04:16:30 | ftsf | ahoy! |
04:16:37 | ldlework | you seem in a good mood |
04:16:57 | ftsf | hmm, counting down the days. pretty tired today |
04:17:06 | ftsf | too much celebratory drinking last night |
04:32:53 | * | smt joined #nim |
04:50:08 | * | Nobabs27 quit (Quit: Leaving) |
06:07:58 | ldlework | ftsf: I'm getting closer to arbitrary-type port system |
06:08:32 | ldlework | dunno if its even useful but its been an interesting challenge |
06:09:04 | ftsf | cool, still using the concept stuff? |
06:13:51 | ldlework | ftsf: nah object variants |
06:14:16 | ftsf | oh, don't think i've heard of those before |
06:14:37 | ldlework | the thing is you can't actually store a list of object that are generic |
06:14:50 | ldlework | I assume because you need to know how the data is packed to know how to allocate |
06:15:04 | ldlework | but you can store a list of object variants |
06:15:35 | ldlework | which admittedly involves a bunch of case/when but you can write the api so that the port layer takes care of it all and hides it from clients |
06:15:58 | ldlework | ftsf: here's some unit tests, https://gist.github.com/dustinlacewell/225e9e0ad287b025669d2e5a397f1c93 |
06:16:44 | ftsf | cool |
06:16:47 | ftsf | looks nice |
06:17:04 | * | rauss quit (Quit: WeeChat 1.7) |
06:21:48 | ldlework | lol main.nim(37, 68) Error: internal error: expr: var not init result₃47925 |
06:22:04 | ldlework | I am the nim killer |
06:34:46 | * | Vladar joined #nim |
06:38:45 | * | nsf joined #nim |
06:42:00 | * | yglukhov joined #nim |
06:46:28 | * | rokups joined #nim |
06:56:55 | * | shashlick_ quit (Ping timeout: 240 seconds) |
06:57:18 | * | shashlick joined #nim |
07:03:45 | Araq | ldlework: please create a Nim issue |
07:05:47 | * | arnetheduck quit (Ping timeout: 260 seconds) |
07:06:10 | * | arnetheduck joined #nim |
07:30:29 | FromGitter | <Varriount> ldlework: You monster! |
07:32:33 | FromGitter | <Varriount> ldlework: it might take less space to store a list of references, rather than objects. Variants will always take up the amount of memory required by the largest possible case. |
07:32:51 | FromGitter | <Varriount> Since they are backed by C unions. |
07:40:47 | Araq | varriount: I often have the desire to change my compiler just to make your statements wrong :P |
07:41:41 | Araq | there is no inherent reason case objects need to be backed by unions once my case object changes land in Nim devel :-) |
07:42:17 | ldlework | Araq: will your changes allow variants to reuse names? |
07:42:30 | Araq | on the other hand, how would arrays of case objects work then ... hmmm |
07:43:32 | Araq | ldlework: that feature bites with what I have in mind for case objects |
07:44:27 | ldlework | bites? |
07:44:57 | * | Arrrr joined #nim |
07:45:16 | Araq | conflicts. |
07:46:01 | ldlework | What is the utility of object variants? It would seem to be to try to have singular implementations that work on the variants despite the variant. |
07:46:14 | ldlework | Like being able to access a .value on each variant but not some |
07:46:48 | ldlework | you have variants then concepts that describe the structure of similar subsets of variants |
07:46:56 | ldlework | now you can implement stuff against those concepts and all the variants apply |
07:47:00 | ldlework | just rambling here.. |
07:47:19 | * | yglukhov quit () |
07:47:41 | ldlework | but if each variant needs unique names despite sharing the same field type, then you lose the ability to describe shared aspects with concepts |
07:53:29 | FromGitter | <evacchi> why does nimble wait for tasks to end to send the result to stdout ? |
07:53:45 | ldlework | It seems like all these features should go towards sharing more implementations across more types |
07:54:04 | ldlework | with less specification |
08:00:44 | * | yglukhov joined #nim |
08:04:43 | * | couven92 joined #nim |
08:06:08 | * | yglukhov quit (Remote host closed the connection) |
08:09:14 | * | ftsf quit (Quit: :q!) |
08:10:45 | * | yglukhov joined #nim |
08:16:31 | * | samuell joined #nim |
08:20:47 | FromGitter | <dom96> @evacchi there is an issue to fix that, it might be fixed already in master in fact. |
08:20:57 | FromGitter | <dom96> Araq: What features do you have in mind? |
08:21:40 | * | Andris_zbx joined #nim |
08:22:07 | Araq | already explained it in the forum. make it safe to use, not wild object case branch transitions, primitive pattern matching to ensure at compiletime the accessed field is valid |
08:22:26 | Araq | like Haskell, ML, Rust, etc etc do it. |
08:23:21 | Araq | this means at construction you need to give it a concrete enum value so that the compiler can check for consistency. zahary already implemented large parts of it in a branch |
08:24:11 | couven92 | Question: why does nimble create symlinks for binaries on Linux, but creates cmd stubs on Windows? |
08:24:43 | Araq | couven92: because Windows symlinks require admin rights to create and Win XP lacks symlinks altogether |
08:25:12 | couven92 | Araq, ah... right, sry I forgot the Admin thing... |
08:25:16 | Araq | and the cmd stubs don't work btw, osproc.execProcess cannot run .cmds out of the box |
08:25:39 | Araq | because that requires a batch shell to run them |
08:26:08 | couven92 | There is actually another problem as well: if you invoke a nimble binary with a very long command-line argument list the Command Prompt fails stating that the argument list is too long |
08:26:31 | Araq | it's simply a bad idea to make Nimble build end user programs. I have said it before, nobody listens. |
08:26:38 | couven92 | ah |
08:27:16 | couven92 | so, ovwerwrite the build taks in the nimble with the correct nim compile command-line? |
08:28:02 | couven92 | like `nim c -o:~/.nimble/bin/myMagicPackage myMagicPackage`? |
08:30:09 | couven92 | Araq, btw, I listened to your template advise yesterday... Neat thing! I still doing baby steps in Nim, and each time I learn yet another great thing about Nim! #joy |
08:30:41 | Arrrr | What advise? |
08:30:55 | FromGitter | <dom96> Araq: how does that conflict with allowing the same field names for two different branches? |
08:31:02 | FromGitter | <dom96> it should help in fact. |
08:31:20 | couven92 | Arrrr, He told me to quit copy-pasting and to remember to write template instead! :D |
08:31:29 | Araq | dom96: not if the fields should share the underlying value. |
08:31:40 | FromGitter | <dom96> I am yet to find a language package manager that doesn't offer the ability to create binary packages. |
08:31:49 | Araq | which is what's specified in the RFC. |
08:32:27 | FromGitter | <dom96> There is an RFC? Is it on GitHub? |
08:32:33 | Araq | yeah |
08:33:56 | FromGitter | <dom96> link? |
08:34:54 | Araq | https://github.com/nim-lang/Nim/issues/3629 |
08:34:58 | FromGitter | <dom96> couven92: if you know of better ways then PRs are welcome :) |
08:35:55 | Araq | reading it again |
08:36:16 | Araq | my ideas about case objects are not in conflict with my idea in that RFC. cool. |
08:36:58 | FromGitter | <dom96> Oh, I was looking for a description of your pattern matching/construction idea. |
08:37:09 | ldlework | fwiw rust allows name reuse in variants |
08:37:21 | FromGitter | <dom96> But yeah, what you describe in that issue would be nice. |
08:37:34 | Araq | ldlework: that's just a naming feature afaik |
08:37:50 | Araq | it doesn't mean the fields share the same offset |
08:38:01 | FromGitter | <dom96> If you're going for pattern matching then you may as well go all in and allow what Rust allows. |
08:38:14 | ldlework | I don't even want them to share the same offset necessarilly |
08:38:30 | Arrrr | Name reuse is quite useful for big objects variants |
08:38:31 | Araq | ldlework: but others wanted and it's a cool thing ;-) |
08:38:32 | ldlework | I just want to be able to capture a single implementation over two variants |
08:38:50 | ldlework | If you have two variants that have a field called "foo" |
08:39:11 | ldlework | then having an implementation over a concept that requires foo, allows you to pass either variant to the implementation without discriminating inside the function |
08:39:19 | ldlework | or at least that would be the idea |
08:40:08 | ldlework | that has a lot more value than some space optimization |
08:41:19 | Araq | well you can move the field out of the 'case' part. that works today with the only downside that your type is under specified. |
08:41:31 | ldlework | Not all variants need the field |
08:41:42 | Araq | but types always are, so that's not exactly a new problem. |
08:41:47 | ldlework | what? |
08:41:52 | ldlework | oh |
08:41:56 | ldlework | you were replying to yourself :) |
08:42:04 | Araq | yes. |
08:42:13 | ldlework | But that isn't even good enough |
08:42:26 | ldlework | Moving it out of the case forces all vairants to have the type |
08:42:35 | ldlework | field* |
08:43:04 | ldlework | which obliviates the usecase I just described |
08:43:13 | ldlework | since now there's nothing to concept-ualize |
08:43:23 | Araq | not "good enough" for you. objectively it works. right? |
08:43:26 | ldlework | no? |
08:43:38 | FromGitter | <evacchi> @dom96 cool, I'll check |
08:43:41 | ldlework | it doesn't accomplish the same thing, as I've just described. |
08:44:11 | Araq | you mean because 'when compiles(x.field)' always is true then? |
08:44:14 | ldlework | your problem to object variant name problem just now was "don't use object variants" |
08:44:20 | ldlework | solution* |
08:44:25 | ldlework | yes |
08:44:30 | ldlework | Or anything else |
08:44:42 | Araq | but 'when compiles(x.field)' is true today, since some case branch has this field |
08:45:04 | ldlework | eh? |
08:45:22 | euantor | The weaker case approach for object variants would be brilliant. I've found myself trying to do that a few times then realising that obviously it wouldn't work |
08:45:47 | Araq | echo x.field # works when 'field' is in a 'case', access is validated at runtime |
08:46:24 | Araq | so 'when compiles(x.field)' is also true. (in today's Nim.) |
08:46:41 | Araq | and concepts are build on top of 'system.compiles' |
08:46:45 | Araq | *built |
08:50:23 | ldlework | Araq: consider this code, https://gist.github.com/dustinlacewell/345bc4d37be762118123aea6f029ad96 |
08:50:32 | ldlework | I just wish I could collapse this kind of thing somehow |
08:51:00 | ldlework | the compiler should know when I'm using the bool or the int kind, and so, I should just always be able to use .value and have it be typed correctly |
08:51:11 | ldlework | even if it has to expand out implementations as if it were generic, I don't mind |
08:52:05 | ldlework | The Inlet object is a variant so I can store a seq[Inlet] |
08:52:19 | ldlework | instead of several disjoint homogenous lists |
08:52:58 | ldlework | the idea is to have some kind of type-generic container, so that the api never requires you to specify the specific types you're using, but then, enforces that only containers of the same type can send each other values |
08:56:16 | ldlework | The ultimate implementation I think, would not require me to know all of the types that will be put into the containers ahead of time |
08:56:21 | ldlework | using an enum as a switch |
08:56:30 | ldlework | and having case/of handling everywhere |
08:56:40 | ldlework | that slightly handles each internal type slightly differently |
08:56:41 | Araq | well getting rid of the boilerplate is just a macro/template away |
08:57:03 | ldlework | Sure, but then I make it opaque |
08:57:20 | ldlework | My implementation right, despite being variant based, and repetitive, is quite beautiful |
08:57:36 | ldlework | But I really hope that the type system keeps getting stronger and stronger |
08:57:59 | ldlework | I will post my implementation once complete and maybe it can be used to think about it |
08:59:16 | ldlework | Even with a macro, you'd need to know ahead of time all of the types you'd want to support. |
09:00:16 | * | ftsf joined #nim |
09:00:20 | ldlework | I think its possible that just concepts alone, no matter the implementation, wouldn't be able to solve the "any-type-container" problem |
09:01:00 | ldlework | however, a concept system that worked cleverly with the variant system might just be able to vanquish the repetition in representing how to store arbitrary containers |
09:01:16 | ldlework | (even if those containers are as big as how many possible types you contain across your program) |
09:01:53 | ldlework | For example, what if you wanted to write a library that supplied this system? And the end user just used the system to register a container with a new type? You couldn't do that because the library needs to know all the types ahead of time. |
09:02:18 | ldlework | Anyway, just some rambling. |
09:02:29 | Arrrr | Cannot be used inheritance here? |
09:02:42 | ldlework | that's runtime dispatch |
09:03:04 | ldlework | I want the compiler to go "woah, you're connecting an outlet[A] to an inlet[B] |
09:03:12 | ldlework | no matter what A or B are |
09:03:13 | Arrrr | Yeah, but object variants have costs too |
09:03:32 | ldlework | sure, that's why I'm speaking inspirationally about making the type system ever stronger |
09:04:02 | Arrrr | Having a seq for each enum value would reduce that cost |
09:04:12 | ldlework | also methods are like dangerous since they're being threatened to be removed time to time |
09:04:34 | ldlework | sure but we're back to having to know all the types ahead of time |
09:04:44 | ldlework | and now we're just going further away from using a type system |
09:04:45 | Arrrr | That's a meme, Araq won't do that |
09:04:51 | ldlework | and just using multiple arrays to store things |
09:04:57 | ldlework | sorry? |
09:05:05 | ldlework | oh methods |
09:05:50 | Araq | you dream about new features, I dream about removing old features. and I think this will make Nim stronger. :-) |
09:06:05 | ldlework | basically I don't mind using a union to have a single seq[] which can be iterated, since that's precisely the goal |
09:06:15 | ldlework | the code that uses this system doesn't need to know about all the types |
09:06:26 | * | Sentreen quit (Quit: WeeChat 1.4) |
09:06:30 | ldlework | it can just iterate over them generically, pumping data between connected ports without a care in the world |
09:06:45 | * | Sentreen joined #nim |
09:06:50 | ldlework | but it should be the type system that constructs the union |
09:06:55 | ldlework | by knowing all the uses, etc |
09:07:26 | ldlework | allowing for librarification of the system as well |
09:11:37 | ldlework | heh I think the ultimate expression of this would be a concept system that would somehow allow me to store a sequence of referneces to arbitrary types that satisfied the concept |
09:11:43 | ldlework | so the sequence just stores references |
09:11:52 | ldlework | but each reference can be to an arbitrary type |
09:11:52 | * | vlad1777d joined #nim |
09:12:07 | ldlework | just so long as the referenced type is valid for the sequence |
09:12:21 | ldlework | I can see how this is just impossible for values other than pointers |
09:12:42 | ldlework | now all you need to do, is write a wrapper for your basic type that is valid for the concept |
09:12:48 | ldlework | and it can be added to the sequence |
09:13:11 | ldlework | that sequence can be iterated, and any part of the concept interface can be interacted upon the arbitrary ref types |
09:13:26 | ldlework | I wonder if there's any language that allows this |
09:13:37 | ldlework | type safe language that is |
09:13:47 | * | couven92 quit (Ping timeout: 240 seconds) |
09:14:48 | Arrrr | You can do that with macros. If i understand correctly. |
09:15:10 | FromGitter | <dom96> Huh, this offset thing in object variant fields. If it's so useful maybe it should be behind a pragma? |
09:15:19 | FromGitter | <dom96> I don't see the advantages that it gives tbh |
09:15:44 | ldlework | Arrrr: what, store arbitrary references in a sequence and access them as homogenous providers of a concept?! |
09:16:25 | ldlework | And a macro implies that you have to know all the types upfront |
09:16:48 | ldlework | this obliviates the whole point of having the type system know all of the types that are valid for the concept |
09:17:00 | ldlework | and being able to define a sequence of references to arbitrary implementors of the concept |
09:17:08 | ldlework | I can't see how a macro would allow for this behavior |
09:17:12 | ldlework | (or any language I've heard of) |
09:18:33 | ldlework | my conclusive two-cents is that nim's killer feature is its declarative structural typing |
09:18:46 | ldlework | put all your pennies in that pot |
09:18:51 | Arrrr | Well, i think that if you care about performance, you would want to craft by hand how to process the information instead of hiding this with concepts. And if you don't, you could always use inheritance. |
09:19:16 | ldlework | its about having type safety up-front though |
09:19:55 | Arrrr | But type safety goes against performance. You can't get more safe than using methods |
09:20:02 | ldlework | what |
09:20:07 | Araq | what indeed. |
09:20:09 | ldlework | why does type safety go against performance? |
09:20:35 | Araq | I think ldlework's ideas are close to what an entity component system would give us? |
09:21:10 | Araq | which is on my todo list since some time because everybody gets it wrong :P or maybe I'm too ignorant. |
09:21:55 | ldlework | I dont know, I'm just thinking that being able to declaratively describe aribtrary structural features of types and having those create typeclasses |
09:22:25 | ldlework | the more and more those typeclasses can be used as normal types, the more and more you can have singualr implementations cover more types |
09:23:05 | ldlework | Nim's already fast, and it has a full procedural core to the langauge. You can already use traditional CS to write really fast programs in it. |
09:23:30 | ldlework | With concepts it has the chance to be insanely expressive. Even given its crazy macro system. |
09:23:51 | ldlework | Like, not only does it give you great meta-prorgramming when the generics system can't express your isomophic implementations |
09:24:12 | ldlework | But it also pushes the boundry / raises the bar to how dense of isomorphic implementations can be represented |
09:24:39 | ldlework | Especially if the core PoC is already there, which it is, its already hella useful. |
09:24:41 | * | Arrrr quit (Ping timeout: 268 seconds) |
09:24:51 | ldlework | But you run into segfaults and limitations |
09:25:11 | ldlework | And I couldn't figure out how to store the data of various concept-adhering types in a single array without object variants |
09:25:20 | ldlework | but concepts did not help me hide the variations |
09:25:22 | * | Arrrr joined #nim |
09:25:24 | ldlework | that's where I'm at. |
09:26:07 | ldlework | Like you could enforce a semantic in the language that |
09:26:20 | ldlework | You can define fields and so on of concept types |
09:26:26 | ldlework | but they all have to be reference types |
09:26:40 | ldlework | imagine having a type, and one of the field types was defined as a concept |
09:27:08 | ldlework | now you can stick a reference to any value of any type that adheres to the concept |
09:27:40 | ldlework | I don't think there's a language on earth that can specify structure details through typeclasses. |
09:28:54 | ldlework | I suppose the problem with storing a list of references of differing types that adhere to a concept is |
09:28:59 | ldlework | how do you know how to call things on the concept |
09:29:07 | ldlework | and how do you know the offsets of the shared fields on the various types |
09:29:23 | ldlework | but how does it work when sending various concept adhering types through function calls? |
09:29:40 | ldlework | conceptualize all the things! |
09:32:17 | ldlework | its pretty neat that I can write code like this, but https://gist.github.com/dustinlacewell/95d8dcda2d4c9ade42641d42a7fd560b |
09:32:24 | ldlework | you can just taste the isomorph |
09:33:26 | Araq | code like this is not the problem, it can be made shorter with a macro/template. |
09:34:25 | Araq | and your other points I can summarize as "generics are viral" |
09:37:00 | Araq | it's not clear to me if the problem with "code like this" is its repetitive nature or its closed form. |
09:38:58 | FromGitter | <dom96> Araq: Isn't the necessity for the fields having the same offset rare? |
09:39:06 | FromGitter | <dom96> (in object variants) |
09:39:28 | Araq | dom96: I don't know. let's ask euantor. |
09:40:01 | euantor | Why me? |
09:41:29 | euantor | Whenever I've used object variants, I've been writing code only used from Nim rather then wrapping a library or exporting the types to be used elsewhere. In that case, the offset doesn't matter much to me I just want it to work |
09:44:09 | Araq | "The weaker case approach for object variants would be brilliant. I've found myself trying to do that a few times then realising that obviously it wouldn't work" |
09:44:36 | Araq | ^ doesn't this refer to the idea of offset sharing? |
09:44:47 | euantor | No, not as far as I udnerstand |
09:45:51 | ldlework | Saying that macros can finish off some isomorph that you cant express with the type system is crucially tautological |
09:46:02 | ldlework | i mean that in a constructive tine |
09:46:16 | euantor | https://www.irccloud.com/pastebin/v1wCP7kj/ |
09:46:30 | ldlework | it doesnt actually address where the line of expressibility is and whether it can be improved |
09:46:37 | euantor | That's the kind of thing I've found myself wishing I could do. Apologies if I'm just not understanding the terminology |
09:46:41 | ldlework | as i admit its already very very good |
09:47:38 | ldlework | but the virality of generics does emphasize my point a little, even given the awareness of metaprogramming availability |
09:47:44 | euantor | Very similar to Rust's tagged enums: https://doc.rust-lang.org/book/enums.html |
09:49:33 | ldlework | also macros cant solve the problem entirely as then you cant extend the system |
09:50:14 | ldlework | unless you force clients to run some finalizer macro that builds the composite implementation but its just ugly anti pattern |
09:50:32 | ldlework | see my ecs |
09:51:13 | ldlework | which would be nice if they could just import it, implement components that are valid for a concept and boom they are inputable and attachable to entities |
09:51:33 | ldlework | but right now clients are forced to execute an aggregation macro |
09:52:02 | ldlework | which is confusing and hard to explain the nuances of its use, and hard to justify |
09:55:53 | FromGitter | <dom96> euantor: Judging by the issue that Araq mentioned above it seems that that is already planned. |
09:56:16 | euantor | Yes, that's what I was referring to, just saying that I 100% support that :) |
09:56:45 | FromGitter | <dom96> What the Rust enums also allow (AFAIK) is that fields can have the same name in two different branches. |
09:57:23 | FromGitter | <dom96> So that this also works: https://gist.github.com/dom96/1f80ede7622e281be21b4f0a77169352 |
09:57:45 | Araq | no, not what it "also" allows, it doesn't have offset sharing |
09:58:33 | euantor | Yes, Rust ENums allow what you showed there dom96, and it's quite nice |
10:00:31 | ldlework | especially if captured by concepts... |
10:01:26 | Araq | Rust doesn't allow the |
10:01:30 | Araq | of a, b: |
10:01:30 | Araq | name: string |
10:01:30 | Araq | of a: |
10:01:32 | Araq | age: int |
10:01:34 | Araq | part at all. |
10:01:44 | FromGitter | <dom96> What is offset sharing good for? |
10:01:48 | Araq | because a|b and just a are not disjoint. |
10:03:00 | ldlework | dom96: saving on memory right? |
10:03:51 | FromGitter | <andreaferretti> well I think for name sharing to work, the compiler needs to know which branch one is in when using that field |
10:04:00 | FromGitter | <andreaferretti> and that is essentially pattern matching |
10:04:13 | FromGitter | <andreaferretti> which Araq mentioned as a possible future feature |
10:04:33 | ldlework | that's what I want concepts to do |
10:04:42 | ldlework | I want to be able to define a concept that describes some of the variants |
10:04:47 | ldlework | define a function that takes the concept |
10:04:59 | ldlework | pass it variants and have it work without type discrimination in the function |
10:05:03 | ldlework | that is glory days right there |
10:05:08 | FromGitter | <andreaferretti> I don't see how concepts would help - they are essentiall constraints |
10:05:16 | FromGitter | <andreaferretti> everything you can do with them, you can do without |
10:05:21 | FromGitter | <andreaferretti> just leave everything generic |
10:05:34 | FromGitter | <andreaferretti> the point is when you don't know statically the types |
10:05:34 | ldlework | Then you can't store the values in a sequence |
10:05:43 | FromGitter | <andreaferretti> otherwise, there is no need to use variants |
10:05:53 | ldlework | variants allow you to store a homogeny |
10:06:16 | FromGitter | <andreaferretti> in all cases where variants are useful |
10:06:32 | FromGitter | <andreaferretti> it is because which variant is actually in play is unknown until runtime |
10:06:33 | ldlework | I suppose what I said about the concept doing all the descrimination was wrong |
10:06:59 | * | PMunch joined #nim |
10:07:07 | FromGitter | <andreaferretti> concepts are constraints |
10:07:13 | ldlework | I understand that... |
10:07:20 | FromGitter | <andreaferretti> they allow us to express something |
10:07:27 | FromGitter | <andreaferretti> but everything you can do with them |
10:07:32 | FromGitter | <andreaferretti> you could do before |
10:07:40 | ldlework | what |
10:07:40 | FromGitter | <andreaferretti> just leaving the generic type unconstrained |
10:07:48 | ldlework | .... |
10:07:58 | FromGitter | <andreaferretti> nim specializes generics |
10:07:59 | ldlework | what you do with concepts is precisely further constraining the generic type |
10:08:14 | FromGitter | <andreaferretti> which is useful to make things more readable |
10:08:16 | ldlework | so saying, without them, you could do everything you could before is a strange way to frame things |
10:08:20 | FromGitter | <andreaferretti> but if you omit it |
10:08:21 | ldlework | its not just for readability |
10:08:24 | FromGitter | <andreaferretti> it works the same |
10:08:27 | ldlework | no |
10:08:36 | ldlework | it weakens compiletime security |
10:08:45 | FromGitter | <andreaferretti> it doesn't |
10:08:55 | FromGitter | <andreaferretti> because eventually nim specializes that generic |
10:08:57 | ldlework | if I just have a T |
10:09:03 | ldlework | I don't know what fields are available for the T |
10:09:08 | ldlework | if I have a T: SomeConcept |
10:09:09 | FromGitter | <andreaferretti> and at that point T is checked |
10:09:20 | ldlework | suddenly the implementation can use fields defined on SomeConcept |
10:09:31 | ldlework | its stronger than you're characterizign it |
10:09:32 | FromGitter | <andreaferretti> try it for your self |
10:09:47 | FromGitter | <andreaferretti> you *can* use whatever fields on a generic type |
10:10:16 | Araq | dom96: it comes up all the time, in the Nim compiler itself I could make use of this feature |
10:10:16 | FromGitter | <andreaferretti> it will just fail when you specialize the type if the field does not exist |
10:11:41 | FromGitter | <andreaferretti> ```code paste, see link``` [https://gitter.im/nim-lang/Nim?at=58e6145e68bee3091f1687e4] |
10:12:02 | FromGitter | <andreaferretti> this works, even if in the proc `foo` you know nothing about the type `A` |
10:12:14 | FromGitter | <andreaferretti> in particular you don't know that `A` has a field `bar` |
10:12:48 | FromGitter | <andreaferretti> no need to define a concept `HasBar` |
10:13:03 | FromGitter | <andreaferretti> now, concepts *do* make things more readable |
10:13:10 | ldlework | tada, https://glot.io/snippets/eooli9xvm8 |
10:13:31 | ldlework | I can pass WithFoo but NOT WithoutFoo to conceptual() |
10:13:40 | ldlework | today you learned? |
10:14:18 | FromGitter | <andreaferretti> nope |
10:14:27 | FromGitter | <andreaferretti> I can pass WithFoo but NOT WithoutFoo to general() |
10:14:30 | FromGitter | <dom96> Araq: Okay, that still doesn't answer my question. But that doesn't matter. My point is that we can support both cases with a pragma, can't we? |
10:14:30 | FromGitter | <andreaferretti> :-P |
10:14:49 | FromGitter | <andreaferretti> it is just the error message that changes |
10:14:59 | FromGitter | <andreaferretti> because the check happens later |
10:15:05 | Araq | dom96: we can even support both cases without a pragma |
10:15:09 | ldlework | I see. |
10:15:26 | FromGitter | <andreaferretti> but still, both implementations work with WithFoo and fail with WithoutFoo |
10:15:33 | ldlework | Yes I see that now. |
10:15:35 | FromGitter | <dom96> Araq: great, so let's do that. |
10:15:41 | FromGitter | <andreaferretti> :-) |
10:16:04 | FromGitter | <andreaferretti> now, don't misunderstand me, concepts are useful to organize stuff |
10:16:10 | FromGitter | <andreaferretti> and they improve the error messages |
10:16:22 | FromGitter | <andreaferretti> it makes sense to use them |
10:16:47 | ldlework | are they not also useful for things like `when T is SomeConcept:` |
10:17:07 | ldlework | I suppose you can use compiles($the_entire_concept_definition) in each case |
10:17:08 | FromGitter | <andreaferretti> yes, that is a valid use case |
10:17:31 | FromGitter | <dom96> That's precisely what concepts are, just compiles(concept) :) |
10:17:33 | FromGitter | <andreaferretti> it will definitely be better than compiles |
10:17:40 | FromGitter | <andreaferretti> more clear |
10:17:41 | FromGitter | <dom96> (Pretty much) |
10:18:14 | FromGitter | <dom96> Araq: does this mean my example will work? |
10:18:21 | ldlework | How does one make an extensible system in a type safe language |
10:20:32 | Araq | dom96: I think so. |
10:26:57 | ldlework | here there's no way to properly implement this, is there? https://gist.github.com/dustinlacewell/9e922232f9a1584f023644b3280c5497 |
10:27:14 | ldlework | because it can never know what T there are |
10:27:19 | ldlework | because no value is ever passed, only returned |
10:27:21 | ldlework | heh |
10:27:39 | ldlework | Maybe golang is the answer.... |
10:28:20 | ldlework | none of this cool stuff ever ends up being helpful and you just end up managing distinct implementations and arrays and so forth |
10:28:30 | FromGitter | <andreaferretti> I don't think you can do this in go as well |
10:28:34 | ldlework | maybe by not having generics you just free yourself from thinking about it as well |
10:28:43 | ldlework | andreaferetti, that's not what I meant :P |
10:28:50 | FromGitter | <andreaferretti> the point is that T is not known at compile time |
10:28:55 | ldlework | Yes, I know |
10:29:22 | ldlework | A problem you only encounter if you have generics and try to implement a generic adapter :P |
10:29:39 | FromGitter | <andreaferretti> this is what variant types are for, but you already seem to be using a variant type as input |
10:29:53 | ldlework | yes... |
10:29:54 | FromGitter | <andreaferretti> I am not quite sure what you want to do here |
10:30:01 | ldlework | get the varying field out, obviously |
10:30:05 | ldlework | each variant has a unique field |
10:30:15 | FromGitter | <andreaferretti> yes, that was clear |
10:30:16 | ldlework | I'm trying to hide the internal implementation |
10:30:23 | FromGitter | <andreaferretti> but get it out to use it where? |
10:30:27 | ldlework | for example there is a unified set() method |
10:30:35 | FromGitter | <andreaferretti> I mean, the value is the variant type |
10:30:54 | FromGitter | <andreaferretti> then you can use a case statement at the usage site |
10:31:14 | ldlework | yes, that's exactly what we want to avoid |
10:31:35 | Araq | ldlework: all this stuff is tremendously helpful for entity component frameworks etc but you are so keen on having a single 'seq' that you don't see it. |
10:32:05 | ldlework | If there isn't a single seq where each thing implements the interface that the client knows about |
10:32:17 | ldlework | then it refutes all of the utility of the whole design |
10:32:37 | ldlework | the whole point is that part of my program wont have to know about every single supported data type that can flow between inlets and outlets |
10:32:42 | Araq | no it doesn't and now I'll leave you alone with your ramblings and misconceptions. |
10:32:49 | ldlework | it just goes over all the inlets and outlets and transfers the data between them |
10:32:51 | FromGitter | <andreaferretti> well, you can use references and methods for that |
10:33:05 | FromGitter | <andreaferretti> make a base type |
10:33:13 | FromGitter | <andreaferretti> make `set` into a method |
10:33:15 | FromGitter | <andreaferretti> et violà |
10:33:19 | ldlework | I'm the one defining the conditions of value here, so i don't know why you're taking it personally Araq |
10:33:19 | FromGitter | <andreaferretti> I hope :-P |
10:33:39 | ldlework | And its not like I'm being super vague. My ramblings are an effort to expound my ideas so they're easier to understand. |
10:33:55 | ldlework | Thanks for effortlessly dismissing me out of hand though. |
10:34:26 | FromGitter | <andreaferretti> at the end of the day, some kind of dynamic dispatch has to happen, so it is either methods, or variant types, or something like this https://networkos.net/nim/collections.nim/doc/api/collections/iface.html |
10:34:28 | ldlework | I guess I shouldn't spend days on end trying to think about how to push Nim to its limits. |
10:34:37 | FromGitter | <andreaferretti> it is not a limit of Nim |
10:34:50 | FromGitter | <andreaferretti> it is a tradeoff that you have in every language |
10:35:10 | ldlework | I never said anything was exclusive to nim |
10:35:32 | FromGitter | <andreaferretti> here at least you can choose three different approaches |
10:35:43 | FromGitter | <andreaferretti> they should all work |
10:36:06 | FromGitter | <andreaferretti> something somewhere must be checking some runtime tag to interpret the correct value |
10:36:11 | * | ldlework shrugs. |
10:36:14 | ldlework | o/ |
10:39:16 | Arrrr | He wants the benefits of processing homogeneous data in memory but not having to implement type by type, instead using object variants, which could produce faster code than using ref types, but in my opinion, if you need that speed you'd wish more control over what you are doing, which i don't think you can gain if you make everything abstract/concept |
10:39:32 | * | couven92 joined #nim |
10:40:27 | Arrrr | If i want to go faster than refs, i want to process the same operations to the same data always, but with objects variants you have mispredictions |
10:40:57 | Arrrr | That's why i said it was better to have different seqs for different objects instead of object variants |
10:41:06 | ldlework | its not extensible |
10:43:02 | FromGitter | <andreaferretti> a base ref type is extensible |
10:43:38 | * | vendethiel- joined #nim |
10:43:39 | FromGitter | <andreaferretti> https://networkos.net/nim/collections.nim/doc/api/collections/iface.html is extensible |
10:43:47 | FromGitter | <andreaferretti> sorry, I don't have many more ideas |
10:44:39 | * | vendethiel quit (Ping timeout: 260 seconds) |
11:02:22 | subsetpark | andreaferretti, you got a guy tweeting at you about a nim job! |
11:04:54 | FromGitter | <andreaferretti> uh? |
11:05:04 | FromGitter | <andreaferretti> I don't follow twitter much |
11:05:51 | FromGitter | <andreaferretti> and I don't see anything like that |
11:06:08 | FromGitter | <andreaferretti> anyway, I am quite happy where I work now :-) |
11:06:19 | ldlework | I PM'ed you |
11:06:42 | FromGitter | <andreaferretti> where? |
11:06:50 | ldlework | dunno somewhere on gitter |
11:07:14 | FromGitter | <andreaferretti> sorry, I did not get any PM |
11:07:34 | FromGitter | <dustinlacewell> @andreaferretti pretty sure |
11:07:47 | FromGitter | <andreaferretti> ah ok it's with a different username |
11:16:54 | subsetpark | andreaferretti, i mean he's tweeting at you to get a job. @unicredit |
11:19:01 | * | bjz joined #nim |
11:19:15 | ldlework | andreaferetti, good article, https://andreaferretti.github.io/on-rust-and-nim/ |
11:20:58 | * | krux02 joined #nim |
11:28:24 | zachcarter | think I finally got spawn working with a another thread and a channel |
11:28:24 | zachcarter | https://gist.github.com/zacharycarter/1ee11c89ee33c522feed204bad5ca9e0 |
11:29:02 | ldlework | What is the point of a channel if you are using a thread hmm... |
11:29:12 | zachcarter | to communicate with the main thread |
11:29:41 | ldlework | OK I think I'm conflating channel and goroutine in my head |
11:29:45 | ldlework | err coroutine >.< |
11:30:31 | zachcarter | ah yeah so much terminology haha I know how you feel |
11:30:49 | zachcarter | I’m such a noob when it comes to multithreading and concurrency |
11:31:10 | ldlework | I have used twisted for a long time, but it uses cooperative concurrency |
11:31:19 | ldlework | with chainable deferred/promises |
11:31:20 | zachcarter | interesting |
11:31:25 | zachcarter | ahh okay |
11:32:01 | ldlework | I try to avoid threads whenever possible but sometimes you can't |
11:32:19 | ldlework | What's the advantage of loading assets in another thread? |
11:32:27 | zachcarter | loading screens mainly |
11:32:48 | zachcarter | otherwise the render thread gets blocked while the assets are laoding |
11:33:01 | zachcarter | loading* |
11:33:30 | ldlework | I guess threads are the only way to avoid blocking disk io |
11:33:42 | zachcarter | interestingly enough, bgfx uses its own render thread I believe so what I’m doing may be totally unnecessary. I haven’t really tried loading a large number of assets yet |
11:33:49 | zachcarter | I should set up an example like that |
11:34:11 | zachcarter | you can use async / await but I don’t think the image loading routines I’m using support it |
11:34:16 | zachcarter | so I’m stuck with threads :/ |
11:34:32 | ldlework | I don't think async/await helps with blocking io |
11:34:34 | zachcarter | I believe threads / threadpools are preferred for CPU intensive tasks and async / await is preferred for IO intensive tasks |
11:34:45 | ldlework | like if I understand correctly, there is no such thing as async file io, beyond threads |
11:35:15 | zachcarter | hrmm I think the way Nim’s async / await feature works is similar to how nodes works |
11:35:25 | zachcarter | but yeah it uses another thread internally I”m sure |
11:35:27 | zachcarter | I’m sure& |
11:35:31 | zachcarter | for the event loop |
11:35:33 | ldlework | Ya, at least for file io |
11:35:42 | ldlework | you can do non-blocking non-threaded network io |
11:35:50 | zachcarter | ah okay |
11:36:02 | zachcarter | I really need to go through dom’s book haha |
11:36:20 | cheatfate | ldlework, on windows this works, i even can make async file io for bsd systems, but crappy linux don't have such support |
11:36:40 | ldlework | ah |
11:36:59 | ldlework | I have traditionally lived in linux land :) |
11:37:25 | ldlework | here is my current inlet/outlet implementation if anyone is interested, https://gist.github.com/dustinlacewell/0fb6c5a00104a40b4e7f23199fc80ad3 |
11:37:28 | ldlework | all tests are passing |
11:38:04 | ldlework | the end of the test file has the most interesting uses |
11:38:16 | cheatfate | ldlework, ask Linus to get support of aio* functions for epoll |
11:38:27 | * | Andris_zbx quit (Ping timeout: 240 seconds) |
11:39:06 | zachcarter | cool stuff |
11:40:58 | * | bjz_ joined #nim |
11:41:04 | ldlework | now to generalize it into a macro :D |
11:41:20 | ldlework | so I can more easily add new supported data types 9₆ |
11:42:28 | ldlework | Or I could go the method direction |
11:42:34 | ldlework | or interfaces |
11:42:39 | ldlework | choices choices |
11:43:26 | * | bjz quit (Ping timeout: 268 seconds) |
11:45:43 | ldlework | I wonder if andreaferetti will come back eventually and share their ideas about the advantages of base ref type vs interfaces |
11:53:15 | couven92 | In a nim code file, can I check if a `--dynlibOverride` has been specified? |
11:54:16 | zachcarter | good quesiton |
11:54:19 | zachcarter | quesiton* |
11:54:34 | couven92 | zachcarter, almost! :D |
11:55:11 | zachcarter | :P |
11:55:27 | zachcarter | I don’t know the answer couven92 but I think the libcairo bindings handle it like this : https://github.com/ngtk3/nim-cairo/blob/master/src/cairo_pragma.nim |
11:55:43 | zachcarter | so they add some extra defines |
11:55:48 | zachcarter | :/ |
11:56:16 | zachcarter | I don’t think dynliboverride is a define it’s a compiler setting |
11:56:39 | zachcarter | my guess would be no, but I’ll leave it to the experts |
11:57:37 | couven92 | Hmm... yeah... I'm doing Windows API stuff, so I'm considering to introduce a windowsSdk define in addition to dynlib (e.g. to import types and functions from their headers, etc...) |
11:58:01 | zachcarter | why not just do |
11:58:05 | zachcarter | when defined (windows): |
11:58:13 | zachcarter | import windows specific stuff here |
11:58:37 | zachcarter | I probably don’t understand your example is all |
11:58:40 | couven92 | zachcarter, because compiling for/on Windows does NOT imply that you have the Windows SDK nstalled |
11:58:49 | zachcarter | oohhhhh I see what you mean |
11:58:53 | couven92 | yup |
11:58:58 | zachcarter | cross compilation woes |
11:58:59 | zachcarter | :P |
11:59:05 | zachcarter | I go through the same thing with frag |
11:59:11 | zachcarter | when building for android etc |
12:00:00 | zachcarter | well I was going through it, but I just decided to dynamically bind to everything on android which simplified things, but still |
12:00:09 | couven92 | not necessarily crossplat... If you use GCC together with Nim on Windows, you probably don't have the Windows SDK with all the Windows Headers and lib files installed, you just have MinGW GCC and Nim |
12:00:23 | zachcarter | ahhh |
12:00:32 | zachcarter | that’s true |
12:00:46 | couven92 | Therefore, you cannot simply define a Nim type and annotate it with the c header from the SDK |
12:00:51 | zachcarter | I haven’t used windows in a while but I know the sdk was quite substantial in size |
12:00:58 | couven92 | Yup! |
12:00:58 | zachcarter | right |
12:02:29 | couven92 | But, if you actually do have the SDK installed, you'd want to use it also with Nim, instead of relying on how people have ported the C header to Nim... There are some things in those header that do additional optimizations which simply cannot be transferred to Nim... |
12:02:55 | zachcarter | interesting |
12:05:00 | couven92 | So for me, who works with Windows and actually uses the VCC backend... I WANT to have Nim compile against the actual Windows SDK headers (not the Nim'ish interpretation of those). But I certainly get why many people do not want to do that (even when size is not a factor) |
12:08:46 | krux02 | wouldn't you want to always use an os abstraction no matter what you are doing? |
12:09:26 | krux02 | I programmed on windows, too. But even there I always used SDL or glfw for operating system stuff |
12:09:56 | * | vlad1777d quit (Quit: Leaving) |
12:11:20 | krux02 | just ignore what I said, I just read the chat log |
12:15:16 | cheatfate | couven92, everything your `brand new and shiny` SDK gives to you is not used by Nim... |
12:15:25 | cheatfate | its why it has its own declarations |
12:22:01 | * | vlad1777d joined #nim |
12:26:54 | * | vlad1777d quit (Remote host closed the connection) |
12:27:46 | subsetpark | This is interesting stuff http://www.subtext-lang.org/OOPSLA07.pdf |
12:27:46 | * | zachcarter quit (Quit: zachcarter) |
12:29:27 | demi- | i don't see why you wouldn't want to wrap C or C++ headers in higher level abstractions |
12:39:11 | * | Sembei joined #nim |
12:58:17 | FromGitter | <andreaferretti> @subsetpark still not understand what you are talking about. Cannot see any tweet that mentions me |
12:59:03 | subsetpark | https://twitter.com/moigagoo/status/848954829443608577 |
12:59:27 | subsetpark | è voi, o no? |
12:59:29 | FromGitter | <andreaferretti> ah ok |
12:59:59 | * | cspar quit (Ping timeout: 260 seconds) |
13:00:00 | FromGitter | <andreaferretti> @moigagoo please, do not contact unicredit to ask for nim programmers |
13:00:12 | FromGitter | <andreaferretti> the people managing that account are completely unrelated to our team |
13:00:43 | FromGitter | <andreaferretti> all the development you see is just me |
13:00:54 | FromGitter | <andreaferretti> so in case, please contact me directly next time |
13:02:05 | couven92 | Is there a way to conditionally (using a `when`) add pragmas to a type? |
13:07:57 | subsetpark | at least you can use when/else to declare the type with or without |
13:09:18 | krux02 | subsetpark: so decision tables are two dimensional tables |
13:09:53 | krux02 | the problem with all programming languages is, they are sequential text |
13:10:30 | FromGitter | <couven92> subsetpark, I'm declaring an enum with a lot of members, yes having the when outside the type definition works, but then I'd have to declare then entire enum twice, right? |
13:11:58 | subsetpark | Seems like it. You could always use metaprogramming I'm sure |
13:12:40 | FromGitter | <couven92> subset, ah... with a macro, right? |
13:12:53 | FromGitter | <couven92> Or a template? |
13:14:37 | demi- | there is the pragma pragma that you can use when to define what it means, i think that would work |
13:15:41 | FromGitter | <couven92> demi-, that sounds very much like what I'm looking for, thx! |
13:16:56 | FromGitter | <evacchi> so, if I call `fooTask(); barTask()` from another task in nimble it looks it only calls barTask() (foo and bar use setCommand); how do I run them both? |
13:17:50 | demi- | couven92, you should check the nim language guide for these things |
13:17:52 | FromGitter | <evacchi> ( in other words: I assume setCommand is mutating some state; is it possible to execute two tasks in sequence ? ) |
13:19:54 | FromGitter | <andreaferretti> @evacchi I think as the last resort you can do something like this https://github.com/unicredit/cello/blob/master/cello.nimble#L26-L28 |
13:20:09 | FromGitter | <andreaferretti> but it would be nicer to chain tasks natively |
13:29:36 | * | zachcarter joined #nim |
13:29:44 | * | smt_ joined #nim |
13:29:58 | * | BitPuffin|osx joined #nim |
13:31:33 | * | smt quit (Ping timeout: 260 seconds) |
13:37:02 | FromGitter | <stisa> @evacchi does calling `setCommand "nop" ` between commands work? I remember nimble warning me to do it some time ago |
13:43:11 | * | bjz_ quit (Quit: My MacBook Pro has gone to sleep. ZZZzzz…) |
13:43:54 | Sentreen | Does nim offer any communication between threads besides channels? |
13:45:14 | Sentreen | I guess I can allocate memory manually and pass a pointer to that memory when starting my thread, but I just want to know if there is something more high level before I start that... |
13:47:01 | couven92 | can you cimport enum values? How? |
13:47:43 | yglukhov | Araq: why remove min/max vararg behavior? that was handy. |
13:48:29 | FromGitter | <evacchi> @stisa nope, didn't work |
13:48:48 | FromGitter | <evacchi> thinking about doing my own template that calls exec() |
13:49:27 | FromGitter | <Varriount> couven92: What do you mean by "Nim'ish interpretation"? |
13:50:34 | FromGitter | <Varriount> Sentreen: What other kind of communication abstractions could there be? |
13:51:34 | Sentreen | Varriount: I'm thinking many to one "broadcasting". |
13:52:12 | couven92 | @Varriount I'm actually not sure anymore... While continuing I think I defeated my own argument... :P |
13:52:20 | Sentreen | I basically have 'n' (where n is only known at runtime) independent processing pipelines, that occasionally can send data to one of the other pipelines. That communication happens through channels. |
13:53:21 | Sentreen | However, the initialization is tricky, since every pipeline should have a seq through which it can access the communication channels of the other pipelines |
13:53:49 | FromGitter | <Varriount> Hm. That seems like another kind of channel concept |
13:54:04 | yglukhov | Araq: vararg variant seems to work for openarrays as well. |
13:54:19 | Sentreen | I came up with a few ideas, but they seem pretty hacky. Ideally I could have some sort of many-to-one broadcasting channel, that I can use to notify all of my pipelines that pipeline x can be reached at channel x |
13:54:40 | Sentreen | Bonus points because I could add more pipelines at runtime with such a system |
13:55:59 | FromGitter | <andreaferretti> @Sentreen if you manage something nice, please share a library, since it is a pretty common use case |
13:59:06 | cheatfate | Sentreen, maybe this is not many-to-one, but one-to-many? |
14:00:03 | Sentreen | Right, yes. Sorry, I'm lacking caffeine ;) |
14:00:23 | cheatfate | also you can implement this via locking primitives |
14:00:56 | Sentreen | I think that my main concern is the part where I actually share data, besides channels is passing raw pointers around the only way? |
14:01:11 | cheatfate | also its not a good way to have number of threads > 2*CPU |
14:02:06 | * | sz0 joined #nim |
14:02:06 | cheatfate | and in most cases its better to have number of threads == NCPU |
14:02:37 | Sentreen | I'm going for NCPU + 1, where the + 1 is just an entry point that will be idle most of the time |
14:03:02 | Sentreen | or just NCPU, with one "special" pipeline, but that doesn't really matter for this :) |
14:03:35 | cheatfate | also i dont not understand why everybody trying to use channels? they are not needed... allocate memory via allocShared() and share Lock between threads... |
14:04:00 | Sentreen | Ah, allocshared sounds like it is what I need, let me look into it :) |
14:04:14 | FromGitter | <andreaferretti> because you have data living on the heap? |
14:04:23 | FromGitter | <andreaferretti> and you want ot pass it around? |
14:04:32 | FromGitter | <andreaferretti> of course manual allocation is inconvenient |
14:06:10 | Sentreen | Since I'm at it, the docs mention channels are pretty slow. Is it really that horrible? |
14:10:46 | cheatfate | Sentreen, it allocates/deallocates memory in every call to send... to you think its fast? |
14:10:57 | cheatfate | do* |
14:11:24 | * | cncl quit (Ping timeout: 255 seconds) |
14:11:35 | * | cncl joined #nim |
14:11:57 | cheatfate | you can do much faster if you need to transfer data block of constant size... because you don't need to allocate memory for every send |
14:13:28 | * | smt joined #nim |
14:13:55 | Sentreen | I'm sending a variant object, so the size is not constant :/ |
14:14:17 | Sentreen | Oh well, I don't have the time to optimize it right now anyway... |
14:14:40 | Sentreen | If I come up with a good broadcasting system I'll be sure to share it :) |
14:15:12 | * | Guest73656[m] quit (Ping timeout: 255 seconds) |
14:15:12 | * | r4vi quit (Ping timeout: 255 seconds) |
14:15:22 | * | Guest73656[m] joined #nim |
14:16:28 | * | smt_ quit (Ping timeout: 260 seconds) |
14:16:29 | * | r4vi joined #nim |
14:25:01 | krux02 | how do I wrap a c macro? |
14:25:18 | krux02 | I tried to do template and emit but it doesnt work |
14:26:00 | krux02 | I would like to do {.emit: ["offsetof(", a, ", ", b, ")"].} |
14:26:10 | krux02 | but the problem is that this does not have a type |
14:26:18 | krux02 | so how do I make an emit into an expression |
14:26:39 | krux02 | I checked on importcpp that basically works, but then I can't do c code generation anymore |
14:34:54 | * | andris_ joined #nim |
14:40:06 | * | PMunch quit (Quit: leaving) |
14:41:15 | * | smt quit (Quit: Leaving) |
14:41:43 | * | Tiberium joined #nim |
14:42:22 | krux02 | proc offsetof[T](a: typedesc[T], b: untyped): int32 {.importcpp: "offsetof(#,#)".} |
14:43:28 | krux02 | http://ix.io/pOm |
14:44:18 | krux02 | Araq, why is the type argument not passed? |
14:50:27 | * | Tiberium quit (Ping timeout: 256 seconds) |
15:00:22 | FromGitter | <evacchi> @andrea, @stisa I think I'll make a huge string for now :D right now it's the most convenient solution for the task at hand |
15:03:44 | * | planhths joined #nim |
15:09:47 | * | BitPuffin|osx quit (Ping timeout: 240 seconds) |
15:10:48 | * | andris_ quit (Remote host closed the connection) |
15:11:47 | * | BitPuffin|osx joined #nim |
15:17:46 | * | rauss joined #nim |
15:37:43 | * | BitPuffin|osx quit (Ping timeout: 260 seconds) |
15:38:15 | zachcarter | https://gist.github.com/zacharycarter/f5a4ccfc0419450b597816a9b3b47b7e |
15:38:20 | zachcarter | loads 230 images in about a second |
15:38:33 | zachcarter | channels may be slow but they’re easy :P |
15:39:02 | * | BitPuffin|osx joined #nim |
15:55:33 | * | Trustable joined #nim |
15:55:57 | zachcarter | loads a 5mb 100x pretty quickly too |
15:58:47 | * | BitPuffin|osx quit (Remote host closed the connection) |
16:04:58 | dom96 | zachcarter: was spawn not enough? |
16:05:10 | zachcarter | I’m still using spawn |
16:05:23 | zachcarter | but essentially what I want is one thread always running |
16:05:37 | zachcarter | that is responsible for spawning worker threads for loading |
16:06:09 | zachcarter | I was having difficulty just using spawn, and keeping track of / figuring out when all my spawned tasks were complete |
16:07:44 | dom96 | whatever works I guess :) |
16:07:54 | zachcarter | eh I’m not convinced this works either |
16:08:26 | zachcarter | I was like twenty minutes ago |
16:23:44 | * | yglukhov quit (Remote host closed the connection) |
16:31:38 | zachcarter | dom96: I think I’ve accomplished what I want to do just using spawn - https://gist.github.com/zacharycarter/788168b0df363c74a74ee4dc5f57e93c |
16:41:25 | * | smt joined #nim |
16:44:26 | * | sz0 quit (Quit: Connection closed for inactivity) |
16:44:44 | * | smt quit (Client Quit) |
16:46:27 | * | couven92 quit (Ping timeout: 240 seconds) |
16:47:11 | * | Arrrr quit (Ping timeout: 256 seconds) |
16:54:51 | * | smt joined #nim |
16:56:20 | * | Arrrr joined #nim |
16:58:07 | FromGitter | <evacchi> @zachcarter that kind of sounds like a perfect example for an executor service https://github.com/evacchi/nimoy/blob/master/examples/hellotasks.nim |
16:58:48 | zachcarter | hmm |
16:58:57 | zachcarter | is 2 the number of workers? |
16:59:30 | FromGitter | <evacchi> yes |
16:59:45 | FromGitter | <evacchi> thread workers |
17:01:20 | FromGitter | <evacchi> besides you could use actors to notify the progress :-) |
17:01:23 | zachcarter | hmm evacchi: I’ll play with nimoy and see if I can incorporate it into my example |
17:01:44 | zachcarter | I think I could find a couple of uses for it in frag |
17:01:52 | zachcarter | but asset management is definitely one |
17:03:06 | * | krux02 quit (Remote host closed the connection) |
17:09:49 | * | vlad1777d joined #nim |
17:11:56 | zachcarter | evacchi: can you do tasks with arguments? |
17:20:01 | * | yglukhov joined #nim |
17:24:35 | * | yglukhov quit (Ping timeout: 260 seconds) |
17:31:58 | * | beatmox quit (Remote host closed the connection) |
17:35:18 | * | samuell quit (Ping timeout: 246 seconds) |
17:35:37 | * | nsf quit (Quit: WeeChat 1.7) |
17:37:32 | * | yglukhov joined #nim |
17:41:30 | * | beatmox joined #nim |
17:42:48 | * | Jesin quit (Quit: Leaving) |
17:43:53 | FromGitter | <Varriount> @evacchi Does nimoy do multithreading? |
17:44:54 | * | yglukhov quit (Remote host closed the connection) |
17:47:27 | * | Sembei quit (Ping timeout: 240 seconds) |
17:50:57 | * | yglukhov joined #nim |
17:57:42 | * | yglukhov quit (Remote host closed the connection) |
17:58:04 | * | yglukhov joined #nim |
18:00:29 | * | Tiberium joined #nim |
18:10:15 | * | couven92 joined #nim |
18:20:54 | * | planhths quit (Quit: Konversation terminated!) |
18:26:11 | zachcarter | I get the following error with the associated example : https://gist.github.com/zacharycarter/87188fc2983422f64bc3adb2ef8a3766 |
18:26:23 | zachcarter | is it because I’m trying to free memory that’s already been GC’d? |
18:28:32 | * | Matthias247 joined #nim |
18:35:04 | demi- | zachcarter: you can use the awesome address sanitizer to help you :) |
18:35:19 | zachcarter | ooo |
18:36:04 | * | smt quit (Quit: Leaving) |
18:36:15 | demi- | include these lines (uncommented of-course) in your nim.cfg https://github.com/samdmarshall/necromancy/blob/master/src/nim.cfg#L6-L10 |
18:36:52 | zachcarter | thank you! |
18:37:47 | demi- | (this is assuming you are on a mac, otherwise you may need to install llvm tooling to do it) |
18:38:31 | demi- | if you have xcode.app instead of just the command line tools, those paths may have to change to /Applications/Xcode.app/Contents/Developer/Toolchains/blah/blah |
18:38:48 | zachcarter | nope this worked perfect :) just had to change 8.0 to 8.1 |
18:38:54 | zachcarter | ==62275==ERROR: AddressSanitizer: attempting double-free on 0x60600010e320 in thread T0: |
18:41:12 | zachcarter | ahhh okay |
18:41:14 | zachcarter | makes sense |
18:41:55 | zachcarter | well kind of |
18:42:41 | demi- | if you have other debugging flags enabled for the nim compiler you should be able to get a read-out of where you are causing the double-free |
18:44:07 | zachcarter | ah I see them below, thanks |
18:46:13 | couven92 | according to https://nim-lang.org/docs/manual.html#types-pre-defined-integer-types an int is 32-bit on x86 and 64-bit on x64? So int in Nim is NOT the same as int in C? But cint is the same as int in C, right? |
18:53:02 | demi- | couven92: you can also use the fixed width types (u)int[8|16|32|64] |
18:53:25 | demi- | which, if you are working in C i would strongly recommend you do anyway |
18:55:05 | couven92 | demi-, in my case I don't want fixed size, I want the platform specific unsigned integer type... (ULONG_PTR) type in the Windows SDK which is unsigned long on x86 and unsigned __int64 on x64 |
18:55:30 | couven92 | so that would be uint in Nim, right? |
18:55:39 | demi- | or cuint |
18:56:14 | couven92 | demi-, but wouldn't cuint be `unsigned int` in C? |
18:56:40 | demi- | isn't that what you just asked? |
18:56:42 | couven92 | `unsigned int` is still 32-bit on x64! |
18:57:39 | couven92 | so in Nim: `uint` would be 64-bit on x64, and `cuint` would be 32-bit, right? |
18:59:35 | def- | couven92: cuint will be whatever "unsigned int" is with your C compiler / platform |
19:00:15 | def- | but in practice, that's what's common, yeah |
19:01:09 | couven92 | def-, thx, and `uint` will be transpiled to either `unsigned int` (x86) or `unsigned long long` (x64), right? |
19:01:19 | def- | unsigned int in any case |
19:02:19 | def- | ah, uint |
19:02:21 | def- | sorry |
19:02:48 | def- | Nim's uint should become uint32_t on x86, uint64_t on x86-64 |
19:03:27 | couven92 | Yes, that's what I expected from the documentation as well... Thx, wanted to be sure :) |
19:03:41 | def- | see lib/nimbase.h |
19:03:50 | couven92 | easy to get these mixed up! :) |
19:04:09 | def- | https://github.com/nim-lang/Nim/blob/devel/lib/nimbase.h#L330-L346 |
19:08:51 | couven92 | ok new case: The <Security.h> header in the Windows SDK creates compile errors if it is included on its own. It only works if you include the <Windows.h> header BEFORE you include <Security.h>. So how do I do my importC pragmas? I tried to put an emit at the top of my Nim file, but Nim still put the header pragmas includes before anything else... |
19:10:02 | * | Tiberium quit (Remote host closed the connection) |
19:10:45 | couven92 | Hmm... I could just omit the header pragma that goes with the importC symbols, and just emit "include Windows, include Security" at the top... |
19:16:05 | cheatfate | ULONG_PTR is (unsigned long*) in C |
19:17:41 | couven92 | cheatfate, no it isn't |
19:18:48 | couven92 | cheatfate, C:\Program Files (x86)\Windows Kits\8.1\Include\shared\basetsd.h lines 124 and 133. |
19:20:27 | cheatfate | ok, |
19:20:55 | cheatfate | last time i have checked it was pointer, because only pointer in C have same semantic like nim's int/uint type |
19:22:12 | * | Tiberium joined #nim |
19:34:44 | * | Sembei joined #nim |
19:47:52 | * | Vladar quit (Quit: Leaving) |
19:50:56 | * | enthus1a1t quit (Ping timeout: 240 seconds) |
19:51:58 | * | Arrrr quit (Read error: Connection reset by peer) |
19:52:13 | * | enthus1ast joined #nim |
19:58:35 | * | enthus1ast quit (Ping timeout: 260 seconds) |
19:59:16 | * | enthus1ast joined #nim |
20:00:24 | Araq | couven92: importc, header: """#include <Windows.h> |
20:00:34 | Araq | #include <Security.h>""" |
20:01:08 | couven92 | Araq, ah... ok, will do |
20:01:10 | * | CcxWrk quit (Remote host closed the connection) |
20:02:16 | * | rokups quit (Quit: Connection closed for inactivity) |
20:02:28 | * | Tiberium quit (Remote host closed the connection) |
20:09:10 | * | CcxWrk joined #nim |
20:16:31 | * | yglukhov quit (Remote host closed the connection) |
20:17:14 | * | yglukhov joined #nim |
20:23:23 | * | PMunch joined #nim |
20:24:02 | * | zachcarter quit (Quit: zachcarter) |
21:01:19 | * | bjz joined #nim |
21:04:25 | dom96 | wow, you can even have for loops inside of an expression nowadays. This works: https://gist.github.com/dom96/62bee820f732cd25e12999a549196e41 |
21:14:05 | * | rauss quit (Quit: WeeChat 1.7) |
21:20:36 | * | zachcarter joined #nim |
21:21:43 | PMunch | Huh, crazy stuff dom96 |
21:28:13 | zachcarter | so if I call spawn with a procedure, and inside that procedure I make an allocation, that allocation is made on a separate thread right? |
21:33:15 | zachcarter | I’m a bit confused - I’m calling spawn sdl_img.load(…) |
21:34:15 | zachcarter | so I’m guessing that executes in another thread and that thread will have its own GC |
21:34:56 | zachcarter | is there a way to prevent the loaded texture from being garbage collected? |
21:39:49 | * | yglukhov quit (Remote host closed the connection) |
21:43:29 | dom96 | gc_ref |
21:44:03 | * | shashlick quit (Ping timeout: 260 seconds) |
21:44:07 | * | bjz quit (Quit: My MacBook Pro has gone to sleep. ZZZzzz…) |
21:44:35 | * | shashlick joined #nim |
21:46:21 | * | bjz joined #nim |
21:50:47 | cheatfate | zachcarter, when thread exited all memory allocated in thread release to OS. |
21:50:55 | cheatfate | was released* |
21:51:26 | zachcarter | okay that may explain what I’m seeing |
21:51:31 | zachcarter | thanks cheatfate / dom96 |
21:52:13 | FromGitter | <evacchi> @zachcarter nope, tasks are `proc()`'s. You can create a closure though. Like, `proc load(foo: string) = proc loader() = ...foo...` |
21:52:44 | zachcarter | ah okay cool |
21:53:26 | FromGitter | <evacchi> @Varriount it schedules actors (aka tasks that are awoken to react to incoming messages) on an executor -- whose default impl happens to be a thread pool (not Nim's `threadpool`) |
21:56:19 | FromGitter | <evacchi> just to be clear: Nimoy is still WIP; I haven't published yet on Nimble. But feel free to check it out and see if you like it / find it useful etc. |
21:56:24 | * | bjz quit (Quit: My MacBook Pro has gone to sleep. ZZZzzz…) |
21:56:39 | * | nsf joined #nim |
22:08:24 | * | Sembei quit (Quit: WeeChat 1.8-dev) |
22:11:29 | zachcarter | cheatfate / dom96: okay so if I use spawn and then I read from the thread, how can I copy the memory into the local heap of the thread I called spawn from? |
22:13:02 | cheatfate | allocShared() or channels |
22:13:27 | zachcarter | okay |
22:13:41 | zachcarter | thanks |
22:34:12 | * | bjz joined #nim |
22:36:13 | * | Trustable quit (Remote host closed the connection) |
22:36:24 | FromGitter | <Varriount> zachcarter: what parameters does `sdl_img.load` take? |
22:40:21 | * | yglukhov joined #nim |
22:41:13 | * | bjz quit (Quit: My MacBook Pro has gone to sleep. ZZZzzz…) |
22:41:41 | couven92 | Hi, can someone help me with a little template magic, appearently my brain is fried: https://pastebin.com/tNbvgveJ |
22:42:08 | couven92 | Nim tells me: `undeclared identifier: decl` |
22:45:26 | * | yglukhov quit (Ping timeout: 240 seconds) |
22:47:45 | zachcarter | Varriount: just a filename |
22:47:46 | FromGitter | <Varriount> couven92: Line 16 doesn't appear to be indented. |
22:48:00 | FromGitter | <Varriount> zachcarter: Where does it store the texture data then? |
22:48:15 | zachcarter | it returns this object |
22:48:39 | zachcarter | https://github.com/nim-lang/sdl2/blob/master/src/sdl2.nim#L552 |
22:48:54 | zachcarter | so inside pixels |
22:49:10 | FromGitter | <Varriount> zachcarter: So.. what procedure does it use to allocate memory? malloc? |
22:49:20 | zachcarter | I’m assuming yeah |
22:49:32 | zachcarter | I haven’t dug too far into that though |
22:50:00 | PMunch | couven92, line 6 is not the proper indentation.. |
22:50:34 | FromGitter | <Varriount> Although, why the compiler doesn't complain about the `else` first, I don't know. |
22:50:39 | couven92 | sry, that was only a copy paste error, just imagine that it was properly indented |
22:50:46 | zachcarter | using allocshared seems to work I think |
22:50:49 | zachcarter | at least in my test |
22:52:14 | FromGitter | <Varriount> zachcarter: If SDL isn't using Nim's allocation procedures, I'm not sure the texture data is tied to a thread. |
22:52:37 | zachcarter | ah okay |
22:52:50 | couven92 | okay just to prove that the indentation error in line 6 wasn't the issue: https://pastebin.com/Bzfctjcd |
22:53:06 | zachcarter | maybe the errors I’m encountering aren’t related to GC’d memory then |
22:53:10 | zachcarter | that was just my first guess |
22:53:42 | * | bjz joined #nim |
22:54:17 | couven92 | I get: line 5: invalid indentation, line 5: undeclared identifier decl, and line 6: expression expected, but found 'keyword else' |
22:55:02 | * | nsf quit (Quit: WeeChat 1.7) |
22:56:02 | FromGitter | <Varriount> zachcarter: I would investigate how SDL is allocating the data though. |
22:56:14 | zachcarter | okay |
23:00:34 | FromGitter | <Varriount> couven92: Does such a technique fail with simpler templates? (for example, generating a less complex type with less paramters) |
23:01:46 | couven92 | @Varriount it worked fine when I removed the decl parameter and did not generate a compound object |
23:02:32 | FromGitter | <Varriount> I mean, are you able to inject a type body in very small, simple tests? |
23:02:46 | couven92 | But in that case, the template generates an entirely valid type declaration... In the example I posted, it kinda does, but maybe in Nims eyes not really... |
23:03:04 | couven92 | Hmm... crazy idea: change the template return type to untyped... |
23:03:51 | cheatfate | couven92, check your line 6 spaces |
23:04:33 | couven92 | cheatfate, not the issue! We checked that already! |
23:06:45 | zachcarter | Varriount: I think I figured out my problem |
23:06:57 | zachcarter | I was calling bgfx texture creation functions from the spawned procedure |
23:07:19 | * | bjz quit (Quit: My MacBook Pro has gone to sleep. ZZZzzz…) |
23:11:34 | * | smt joined #nim |
23:12:32 | couven92 | Ah! I have an idea: Declare the compound as a type markup without any pragmas and then create the imported type as being of that markup type |
23:14:47 | * | Matthias247 quit (Read error: Connection reset by peer) |
23:15:44 | couven92 | This works: https://pastebin.com/2fRrkVGR |
23:19:40 | * | PMunch quit (Quit: leaving) |
23:20:43 | zachcarter | http://imgur.com/a/fplO4 |
23:20:43 | zachcarter | cool |
23:20:47 | zachcarter | async asset loading |
23:22:38 | couven92 | Hmmm... didn't work... My success feeling was premature... Hmmm... will have to take a look again tomorrow... Good Night! |
23:23:01 | * | couven92 quit (Quit: Disconnecting) |
23:28:31 | * | vlad1777d quit (Quit: Leaving) |
23:37:52 | * | bjz joined #nim |
23:38:26 | * | brson joined #nim |
23:46:48 | * | bjz quit (Quit: My MacBook Pro has gone to sleep. ZZZzzz…) |
23:57:49 | * | cspar joined #nim |