00:06:53 | Araq | perhaps I should develop software differently |
00:11:57 | Araq | I write code and fix bugs, I never ask "where is X declared? is it part of the stdlib? is it a babel package? what's its type signature? what does that abbrev stand for?" ;-) |
00:24:06 | OrionPKM | you might if you ever used someone else's code |
00:24:37 | OrionPKM | it's just my personal preference to organize imports by whats in MY code vs whats in standard code |
00:25:06 | OrionPKM | import strutils, re then import mymodule |
00:25:25 | OrionPKM | rather than import strutils, mymodule, re, etc all mixed together |
00:25:33 | OrionPKM | I guess I'm just neurotic |
00:26:15 | OrionPKM | I like clean & organize usings in visual studio, it's basically that |
00:31:15 | * | ics joined #nimrod |
00:36:59 | Araq | I never use that in visual studio ;-) |
00:37:34 | Araq | ok I do, but only to play nice with others |
00:38:02 | OrionPKM | you dont find it valuable to know which imports are part of the project you're currently working on vs part of some external library? |
00:38:18 | Araq | no I couldn't care less |
00:38:22 | Demos | I feel like "unused import" could be a warning... maybe |
00:38:26 | OrionPKM | (some of us do like to spread our code out to more than 1 file btw) |
00:38:31 | Araq | clean imports don't find bugs |
00:38:43 | OrionPKM | there's more to life araq |
00:38:54 | Araq | indeed |
00:39:12 | gcr | Can I define a destructor for my own type that's really an alias for a primitive like int? (eg. type GLbuffer = int) |
00:39:19 | gcr | Well i mean I see that I can, but will that do what I want it to? |
00:39:29 | Araq | I don't think so |
00:39:38 | Araq | you can do that for a 'distinct int' though |
00:39:40 | Demos | well then that would no longer be an alias |
00:41:22 | gcr | It *seems* to work without being a distinct int |
00:41:25 | gcr | but ... hm |
00:42:00 | Araq | OrionPKM: that's exactly my point. ;-) Code is not something I print out and put it on a wall because it's beautiful. I write code to accomplish some goal. |
00:42:48 | Araq | there's more in life than just code |
00:44:22 | Araq | and btw it's usually much more interesting *who* wrote the code as opposed to in which file it ended up |
00:44:31 | gcr | Thanks for your help today, Araq. Nimrod's destructors are the only kind of destructor in any language that makes sense to me |
00:48:03 | Araq | wow. really? |
00:48:26 | Araq | thanks |
00:51:59 | Araq | sometimes I like the destructor design we came up with, sometimes I think it's crap ;-) |
00:56:40 | OrionPKM | agree to disagree. |
00:56:58 | OrionPKM | readability is important to me |
00:57:51 | Araq | if you read the list of imports, perhaps ;-) |
00:58:39 | * | DAddYE quit (Remote host closed the connection) |
00:59:06 | OrionPKM | I do. if it's not my code or I haven't looked at it in a wgile |
00:59:07 | * | DAddYE joined #nimrod |
00:59:10 | OrionPKM | while* |
00:59:52 | Araq | Usually I avoid to read anything. Reading is hard and unrewarding. |
01:03:26 | * | DAddYE quit (Ping timeout: 240 seconds) |
01:24:33 | OrionPKM | so who wrote these? |
01:24:36 | OrionPKM | http://rosettacode.org/wiki/Fibonacci_sequence#Nimrod |
01:25:12 | Araq | no idea |
01:25:48 | * | BitPuffin quit (Ping timeout: 252 seconds) |
01:26:20 | Araq | the continuation version is sweet |
01:27:34 | OrionPKM | god. I didn't even know about this syntax; |
01:27:37 | OrionPKM | for i in 0.. <10 |
01:27:58 | Araq | it's an idiom |
01:28:37 | OrionPKM | I've just always done 0.. 10-1 |
01:28:44 | EXetoC | proc `<` |
01:29:17 | Araq | '-1' works too but is bad for your mojo |
01:35:15 | OrionPKM | exactly |
01:36:00 | Araq | btw you should read why intervals should be of the form [a, b) from Knuth iirc |
01:36:32 | Araq | it's common wisdom now and as such of course wrong |
01:53:49 | OrionPKM | shouldn't you sleep now |
01:54:31 | gcr | Is there a way to iterate over several iterators in parallel? |
01:54:40 | gcr | eg. for i,j in zip(list1, list2) |
01:54:56 | gcr | would yield (list1[0],list2[0]), (list1[1], list2[1]), ... |
01:54:59 | Araq | I think there is sequtils.zip |
01:55:58 | fowl | read that as a filename >_> |
01:56:03 | Araq | OrionPKM: I said I don't sleep anymore to get version 0.9.4 out |
01:56:36 | gcr | hm, thanks |
01:57:14 | * | Demos quit (Ping timeout: 264 seconds) |
01:59:39 | * | DAddYE joined #nimrod |
02:00:13 | Araq | good night |
02:00:39 | * | Demos joined #nimrod |
02:01:24 | OrionPKM | ah sounds good |
02:04:29 | * | DAddYE quit (Ping timeout: 272 seconds) |
02:09:49 | * | DAddYE joined #nimrod |
02:10:45 | * | Varriount_ quit (Ping timeout: 248 seconds) |
02:14:06 | * | DAddYE quit (Ping timeout: 240 seconds) |
02:16:58 | * | gcr quit (Read error: Connection reset by peer) |
02:31:24 | * | Demos_ joined #nimrod |
02:33:57 | * | Demos quit (*.net *.split) |
02:33:58 | * | brihat quit (*.net *.split) |
02:40:18 | * | brihat joined #nimrod |
02:51:35 | Trixar_za | This channel has really grown in the last year |
02:53:00 | Trixar_za | Also some of the worse Rosetta code examples are probably mine |
02:58:47 | * | noam joined #nimrod |
03:43:15 | * | brson joined #nimrod |
03:52:06 | * | gcr joined #nimrod |
03:52:59 | gcr | hm, https://gist.github.com/gcr/8129592 |
03:53:07 | gcr | i expect this code to call the destructors for all the types |
03:53:16 | gcr | instead it just prints "GOODBYE 6" implying that it only fired one of the destructors |
03:53:20 | gcr | even though the rest are provably unreachable |
04:00:47 | fowl | if i move the destructor before foo() it destroys c properly |
04:02:43 | gcr | OOOOOOOOH! Forward declarations |
04:02:45 | gcr | Riiight. OK |
04:02:52 | gcr | Phew I thought I was running into a language bug! Thanks, fowl |
04:10:25 | fowl | it should still destroy b tho |
04:10:33 | gcr | wait yeah, that fixes one or two of them |
04:11:10 | gcr | uh hm |
04:12:58 | * | Varriount joined #nimrod |
04:14:30 | gcr | ok back to suspecting a language bug |
04:24:57 | * | EXetoC quit (Quit: WeeChat 0.4.2) |
04:31:16 | * | ics quit (Quit: My MacBook Pro has gone to sleep. ZZZzzz…) |
04:35:30 | * | DAddYE joined #nimrod |
14:58:50 | * | NimBot joined #nimrod |
14:59:07 | dom96 | and we're back |
14:59:38 | Araq_ | dom96: excellent work, thank you |
14:59:40 | * | Hat_and_Cloak quit () |
14:59:44 | dom96 | np |
15:01:19 | * | Araq_bnc joined #nimrod |
15:01:33 | Araq_ | oh yay I'm back too |
15:01:37 | * | Araq_ quit (Quit: ChatZilla 0.9.90.1 [Firefox 26.0/20131205075310]) |
15:01:49 | * | Araq_bnc is now known as Araq |
15:02:49 | * | dom96_ joined #nimrod |
15:06:02 | * | dom96 quit (Quit: Leaving) |
15:06:24 | * | dom96_ is now known as dom96 |
15:06:25 | * | dom96 quit (Changing host) |
15:06:25 | * | dom96 joined #nimrod |
15:11:30 | dom96 | So yeah, I think it's time to switch to digital ocean |
15:33:17 | * | NimBot joined #nimrod |
15:34:44 | dom96 | Guys look what I found: |
15:34:48 | dom96 | https://thestrangeloop.com/news/strange-loop-2013-video-schedule |
15:35:17 | dom96 | The release date for the Nimrod video is January 13th |
15:35:29 | * | dom96_ quit (Quit: Leaving) |
15:39:40 | * | BitPuffin joined #nimrod |
15:44:45 | * | BitPuffin quit (Ping timeout: 272 seconds) |
15:45:04 | OrionPKM | ah, good to know dom96 |
15:45:30 | dom96 | Glad we don't have to wait until April 21 2014 |
15:47:22 | dom96 | Araq_bnc: ping |
15:48:08 | * | ddl_smurf joined #nimrod |
15:51:05 | * | Endy joined #nimrod |
15:56:09 | * | zahary joined #nimrod |
16:39:04 | * | NimBot joined #nimrod |
16:40:21 | * | BitPuffin joined #nimrod |
16:40:45 | * | [1]Endy joined #nimrod |
16:44:10 | * | Endy quit (Ping timeout: 245 seconds) |
16:44:10 | * | [1]Endy is now known as Endy |
16:45:00 | * | BitPuffin quit (Ping timeout: 245 seconds) |
16:48:07 | * | BitPuffin joined #nimrod |
16:52:30 | * | BitPuffin quit (Ping timeout: 245 seconds) |
17:02:43 | * | Demos_ joined #nimrod |
17:05:32 | * | gcr joined #nimrod |
17:12:02 | * | BitPuffin joined #nimrod |
17:12:10 | BitPuffin | dom96: what do you mean plasma ball? |
17:14:11 | dom96 | https://en.wikipedia.org/wiki/Plasma_ball |
17:14:26 | dom96 | a.k.a plasma lamp/globe/sphere/tube etc |
17:15:54 | BitPuffin | dom96: with occolus |
17:16:32 | dom96 | it would make a pretty cool screensaver |
17:16:57 | dom96 | or even a cool thing in some game |
17:17:08 | BitPuffin | dom96: so do it :P |
17:17:26 | dom96 | I know nothing about opengl though and i'm still sick |
17:17:37 | dom96 | and I feel like playing a game instead :P |
17:18:41 | BitPuffin | dom96: so do it :P |
17:18:58 | dom96 | after I watch Home Alone 2 :P |
17:19:07 | Kooda | xD |
17:24:04 | gcr | I used to have one of those. They are as lovely as they look |
17:24:29 | Demos_ | they smell... |
17:24:58 | dom96 | they do lol |
17:25:04 | OrionPKM | how are you still sick dom |
17:25:12 | OrionPKM | do you have AIDS |
17:25:47 | dom96 | I dunno |
17:25:47 | dom96 | I hope not |
17:28:05 | BitPuffin | dom96: don't die |
17:35:22 | * | Mordecai is now known as psquid |
17:40:24 | OrionPKM | if you do, can i have your stuff? |
17:45:44 | dom96 | no |
17:47:25 | BitPuffin | dom96: what about me? |
17:47:56 | dom96 | only some of it :P |
17:54:35 | * | gradha joined #nimrod |
17:59:58 | dom96 | wow, rust just added the ability to test code examples in doc comments. |
18:01:06 | gradha | do they have a hide-this-setup-part keyword for the docstrings? it's on my todo list |
18:01:59 | gradha | or rather than keyword, a convention for hiding by default a part of the snippet which is used to set up the code for it to be compilable |
18:02:15 | dom96 | hrm, not sure. |
18:02:20 | gradha | I was thinking of "code\n### end setup ###\ncode seen in docstring |
18:04:23 | * | DAddYE joined #nimrod |
18:20:59 | bstrie | dom96: well, python's had that for years :P |
18:21:02 | * | fowl joined #nimrod |
18:22:03 | bstrie | gradha: I believe the sentiment is to *not* hide the setup bits. I think people appreciate that the code in the docs can be copypasted into a file and still run |
18:22:22 | bstrie | though it's true that it might be less direct at illustrating the concept |
18:26:40 | dom96 | I think it would be nice if you could hide the "setup" parts. |
18:26:42 | gradha | bstrie: unless we are talking about one liners docstrings have to get to the point, and test setup code can make you miss even the function call |
18:26:52 | dom96 | in the resulting html |
18:26:56 | gradha | my idea was that the comment would fold using javascript, you can still copy/paste all |
18:28:24 | gradha | but first rst needs to be improved, code blocks presumably can have numbered lines |
18:30:04 | * | Araq_bnc is now known as Araq |
18:31:26 | gradha | what's the use for compiler/nimrod.dot? |
18:34:49 | Araq | gradha: you can generate a dependency graph from it iirc |
18:35:08 | gradha | using graphviz, but it's not a generated file, and it is stored in the repo |
18:35:46 | Araq | it's a generated file |
18:35:56 | Araq | it's in the repo by mistake |
18:44:26 | dom96 | Araq: Did you see the video release schedule? Your talk video will be released on the 13th of January |
18:44:47 | * | Demos_ quit (Ping timeout: 272 seconds) |
18:45:14 | gradha | I'm with fowl, let's release nimrod on valentine's day |
18:46:52 | gradha | "-Honey, I got you a statically linked binary under 100k. -Oh, sweet!" |
18:47:02 | Araq | dom96: :O |
18:47:33 | dom96 | Araq: So we better be ready. |
18:47:42 | gradha | any other talks worth watching? the ruby is not slow looks legit |
18:48:38 | Araq | martin odersky's talk is well worth watching |
18:49:10 | Araq | not sure what others are online, they were all worth watching |
18:49:39 | dom96 | https://thestrangeloop.com/news/strange-loop-2013-video-schedule |
18:55:02 | EXetoC | no bad ones eh? :p |
18:55:29 | gradha | did filwit fix the strangeloop slides with mobile or something? |
18:55:39 | Araq | I don't think so |
18:55:44 | Araq | I gave him my sources |
18:55:53 | dom96 | yeah, we need to do that. |
18:56:12 | gradha | you could render to swf, then to html5 |
18:58:04 | Araq | ping zahary |
18:59:16 | * | DAddYE_ joined #nimrod |
18:59:16 | * | DAddYE quit (Read error: Connection reset by peer) |
19:04:54 | * | Demos_ joined #nimrod |
19:12:50 | * | vendethiel quit (Ping timeout: 264 seconds) |
19:27:49 | dom96 | Araq: It seems that the only reason that output is out of order is because of the stderr to stdout redirection |
19:28:55 | Araq | ha, now that's funny :P |
19:30:04 | * | brson joined #nimrod |
19:51:39 | * | radsoc quit (Ping timeout: 272 seconds) |
19:52:11 | * | vendethiel joined #nimrod |
19:54:36 | * | noam quit (Read error: Connection reset by peer) |
20:02:03 | * | brson quit (Ping timeout: 272 seconds) |
20:03:20 | zahary | pong Araq |
20:05:28 | Araq | merry christmas! |
20:05:47 | Araq | did you get the discussion about the delegate pragma? |
20:08:08 | zahary | nope |
20:08:32 | zahary | and merry christmas to you too :) where (when) should I look? |
20:09:30 | Araq | dunno, here is the simple version: my plan was to support overloading of '.' and even '.=' |
20:09:51 | Araq | proc `.`(j: PJson, field: string): PJSON |
20:10:29 | Araq | no pragma no strange a.b --> need to overload b(a) reorderings |
20:11:48 | Araq | I guess your way was the easiest to implement? |
20:11:59 | zahary | well, the pragma is just the registration mechanism |
20:12:23 | zahary | it would work exactly the same if instead snoop on proc `.` definitions |
20:12:46 | Araq | yeah well |
20:13:10 | Araq | you don't just modify the handling of nkDotExpr so there must be something in here |
20:13:20 | zahary | there is a slight semantic difference in how delegating works tho - it is triggered not on each and every dot access, but rather only when there is no matching fields or function call |
20:13:39 | zahary | this allows you to still have methods defined over the JSON type |
20:13:55 | Araq | hmm yeah well this requires some thoughts |
20:14:08 | Araq | if I have: |
20:14:24 | Araq | proc foo(x: Json, y: int) |
20:14:36 | Araq | x.foo(y) is an ordinary call |
20:15:00 | Araq | if I don't have that, it's ()(foo, x, y) |
20:15:25 | Araq | but this means I need to keep in mind what exists for Json |
20:16:07 | Araq | and so I can't really rely on it and must use x["foo"] to be sure |
20:16:41 | Araq | well ... I screwed up the number of params etc. but you get the idea |
20:18:07 | zahary | it's not different than javascript really where even tho the objects have expando semantics, there are still built-in methods |
20:18:16 | zahary | so this is not a particularly good crituque |
20:20:05 | Araq | well I'd argue if '.' is overloaded every access should go over that |
20:20:35 | zahary | yes, and I argue that this is less convenient |
20:20:46 | Araq | and then '.' can decide if 'x.len' is a call or an access |
20:20:58 | zahary | it's useful to have "built-in" methods, besides the dynamically implemented |
20:23:33 | zahary | nothing stops to define a distinct type that uses a delegator for everything, so we are arguing here just about what is the most useful default behavior |
20:26:57 | * | jimmt is now known as jenjimm |
20:27:11 | * | jenjimm is now known as jennjim |
20:27:12 | Araq | well I think its behaviour should be: |
20:27:24 | Araq | 1.) if there is a *field* in that object, use that |
20:27:37 | * | jennjim is now known as jimmt |
20:27:37 | Araq | 2.) otherwise invoke the overloaded '.' |
20:27:46 | * | jimmt is now known as jenjimm |
20:28:47 | zahary | focusing on fields only is not enough - you want to be able to implement on-the-fly FFI for scripting languages lua_object.foo(bar, baz) |
20:28:47 | Araq | otherwise it looks too error prone |
20:29:18 | Araq | yeah and if you go over the '.' you have more control |
20:29:21 | zahary | or on-the-fly talking to web services. server.foo(user = "Araq") |
20:30:08 | Araq | you overload '.' to have control over it, not to have control sometimes a little bit but you don't know really when |
20:30:35 | Demos_ | I agree with Araq on that, but would that not mean you want EVERYTHING to go through the overload |
20:30:42 | Demos_ | including fields |
20:31:12 | Araq | Demos_: you can easily control fields as they are in 1 scope/definition |
20:31:22 | Araq | which is likely in the same module as your '.' overload |
20:31:52 | Araq | or perhaps indeed we should allow to skip '.' if it refers to something defined in the same module |
20:31:58 | Demos_ | right, and if the fields went through the . op than the . op could not access them itself |
20:32:21 | zahary | most languages designers in the past have made the opposite decision - ruby's method_missing, lua's __index meta-methods, python's __getattr__ |
20:32:23 | Araq | that's a minor issue as we can introduce system.`.` |
20:32:31 | zahary | all of them are triggered only as a fallback |
20:32:42 | Araq | true |
20:32:47 | zahary | and as I said, the other behavior is just a distinct type away |
20:33:13 | Araq | distinct types still have their issues though |
20:33:25 | Araq | notably you can't forward '.' etc. |
20:33:29 | zahary | while, in your scenario, my behavior will required a bit awkward "is this implemented?" code |
20:34:39 | zahary | and semantics-aware IDE can paint the dynamic calls in different colors, etc |
20:35:40 | zahary | we should improve the infrastructure around distinct types, but that's another topic |
20:36:30 | dom96 | Araq: devel still fails to boot for me |
20:36:56 | Araq | dom96: huh? what's the error message? |
20:37:07 | dom96 | compiler/vm.nim(123, 35) Info: instantiation from here |
20:37:07 | dom96 | compiler/vm.nim(112, 28) Error: expression 'system' has no type (or is ambiguous) |
20:37:51 | Araq | ah ok, I see |
20:38:19 | Araq | edit vm.nim:112 |
20:38:29 | Araq | make 'move' immediate, dirty |
20:38:34 | Araq | and then it should work again |
20:39:09 | Araq | my version doesn't need it because it's been fixed already |
20:39:21 | Araq | cyclic dependencies are strange :P |
20:40:02 | * | io2 joined #nimrod |
20:40:07 | dom96 | I can't even imagine how it worked for you lol |
20:40:49 | Araq | zahary: my "module scope" solution however provides something you can't easily get with method_missing afaict |
20:41:16 | zahary | what do you mean by module scope? |
20:43:51 | dom96 | Araq: so what should I test? |
20:44:41 | Araq | jester and aporia |
20:45:02 | Araq | and jester should benefit from the new symbol binding rules in templates |
20:45:24 | Araq | in other words 'bind' is now the default |
20:45:30 | dom96 | Well this is disappointing: lib/pure/times.nim(29, 2) Error: cannot 'importc' variable at compile time |
20:46:00 | Araq | bootstrap with -d:useFFI to get that |
20:46:10 | Araq | but I didn't test that on linux yet |
20:46:21 | Araq | works on windows though :-) |
20:46:48 | dom96 | Is it still very limited? |
20:46:53 | dom96 | Can I import sockets? |
20:47:12 | gradha | zahary: aporia doesn't compile for me either with the other gc, what commit are you able to compile? |
20:47:38 | Araq | dom96: not yet but looked easy to support |
20:47:44 | zahary | gradha: I tested in a while back in the master branch |
20:48:32 | Araq | zahary: as I said, everything in the same module as '.' (or perhaps the underlying type) doesn't go over '.', everything else does |
20:48:36 | dom96 | Araq: Importing 'os' fails with: lib/posix/posix.nim(30, 0) Error: internal error: too implement nkFromStmt |
20:49:03 | Araq | lol |
20:50:11 | zahary | well, and you call adding such more intricate rules "less potentially error-prone"? I should mention that the delegators are properly scoped now - they will act only in the scope where the delegator is defined (this goes all the way to nested procs) |
20:50:43 | dom96 | Anything I try to import gives errors... |
20:51:08 | dom96 | What does this new vm bring again? |
20:51:35 | Araq | well it fixes some macro evalutation bugs at least :P |
20:52:37 | dom96 | Aporia fails to compile |
20:52:52 | Araq | what's the error message? |
20:53:01 | dom96 | processes.nim(329, 30) Info: instantiation from here |
20:53:02 | dom96 | processes.nim(300, 6) Error: identifier expected, but found '(event|event)' |
20:53:11 | dom96 | gradha got that IIRC |
20:53:29 | gradha | yep |
20:53:39 | Araq | ok, that's caused by the new templates |
20:54:36 | Araq | zahary: it's less error prone because you're in control over the names in your module |
20:54:56 | Araq | but not over the names from somewhere else |
20:55:00 | * | Endy quit (Ping timeout: 245 seconds) |
20:55:36 | dom96 | jester still works |
20:56:37 | zahary | I think you're thinking in too much abstract terms here - let's get to the actual example where delegators are likely to be used. |
20:57:21 | zahary | limiting the effect of the delegator to a single module is not useful at all - you want to support types like JSON and XML (the delegator is part of the exported public interface) |
20:58:00 | Araq | that's not what I'm proposing? the delegator still is exported |
20:58:16 | zahary | now, I challenge you to come up with a types that don't have useful built-in methods, but have delegators? |
20:58:51 | Araq | I can't follow. the built-in methods should be in the same module as '.' and things are smooth |
20:59:17 | zahary | JSON, XML, the swizzle vector stuff, script/RPC FFIs - they all have useful built-in methods |
20:59:18 | Araq | otherwise the '.' is invoked just like you expect when you wrote the module |
20:59:47 | Araq | again in my proposal '.' simply ends up being called more often |
21:00:05 | Araq | and it's invoked consistently wrt to its defintion |
21:01:06 | zahary | well, this looks like a very minor modification of the current behavior (the difference is only when I import a type and then try to define some more procs over it in my module) |
21:01:26 | Araq | yes that's the difference |
21:01:35 | zahary | and why is that useful? obviously I decided to add the procs so I know what I'm doing |
21:02:19 | zahary | in your scheme, the type with delegator becomes closed for modifications, because any call not originating from its own module will be cached by the delegator |
21:04:51 | Araq | hmm you have a point |
21:05:46 | zahary | and we are sweating too much over this advanced feature that is going to be only rarely used |
21:07:08 | Araq | I disagree, the use cases are very important |
21:07:32 | Araq | and some code bases can end up using delegators excessively |
21:08:10 | zahary | then I'll keep on insisting that method_missing will be fine :) |
21:08:51 | Araq | also your way is "open" but in other ways closed. for instance if I want to inject every call to some object and add aspect stuff to it |
21:09:17 | Araq | but I guess these are not the use cases we care about here |
21:11:17 | zahary | :) well, do you remember by proposal for before/after monkey patching? you said it breaks modularity, but I still keep in mind when thinking about the caas/symbol files |
21:12:29 | zahary | otherwise, I could always refer to the distinct type I mentioned and also with a pragma: push solution that modifies the following procs |
21:12:53 | Araq | well I think we should do that with the TR macros though they serve a different purpose |
21:13:33 | zahary | yes, that too |
21:14:23 | zahary | my outcry back then was about partial procs, which are the bigger feature for me (the ability to build the body of a proc in a distributed way - often as a side effect of generic instantiation) |
21:14:53 | zahary | so that's still in plan, but initially in a "local to module" fashion |
21:28:43 | Araq | what about '.='? we can't do that with your () {.delegate.} solution, can we? |
21:29:10 | Araq | (though maybe it's hard to implement in any case) |
21:30:00 | zahary | yes, it was just an overlooking. I |
21:30:07 | zahary | I'll add support for it |
21:30:37 | Araq | well I still like overloading of '.' more for asthetical reasons |
21:30:53 | Araq | it's consistent with what we do for [] etc. |
21:31:35 | zahary | personally, it'd go with a designated words like "destroy", "delegate", "copy", etc |
21:32:18 | Araq | that's not nimrodic though :P |
21:32:30 | zahary | but I went for consistency with the other special procs - using '.' is fine with me, but don't forget that you are handling calls too |
21:32:47 | NimBot | Araq/Nimrod master 6264551 Dominik Picheta [+0 ±1 -0]: Remove assert in asyncio which causes problems.... 4 more lines |
21:32:48 | zahary | currently, it's proc `()` {.delegate.} |
21:32:55 | Araq | I know |
21:33:03 | Araq | and I find it strange :P |
21:33:26 | Araq | overloading of () is strange anyway and untested |
21:33:58 | Araq | I might remove it from the language but haven't thought about it really |
21:34:15 | zahary | it's useful |
21:34:39 | Araq | no, we have [] and {} which are slightly less ambiguous |
21:35:26 | Araq | can't see where () is particularly useful. we don't have functors |
21:35:50 | zahary | maybe closures are enough to capture all "callable" objects, but I wouldn't rush to remove it just yet |
21:36:24 | Araq | yeah sure |
21:36:34 | Araq | IF overloading of () works, that is |
21:37:00 | zahary | there is a test in the suite for it (I've broken it a few times) :) |
21:38:00 | Araq | yeah well the test suite is lots of fun |
21:38:15 | Araq | noticed it when I wrote the new VM ... |
21:39:54 | Araq | writing the VM: 2 months iirc. Making it pass most of the tests: 3 months |
21:40:46 | zahary | :) |
21:41:19 | Araq | speaking of which: 'getType' is evil and captures PContext |
21:41:44 | Araq | you get around the dependency by using a closure but that's cheating the dependency is still there |
21:42:34 | zahary | well, what do you suggest? the new `is` is also evil - you have implemented only an older version so far |
21:42:52 | Araq | yup :D |
21:42:55 | zahary | I think compiles should also become usable in evals |
21:43:17 | zahary | so, another case of PContext dependency |
21:44:55 | zahary | I'm also not entirely sure that just making the PContext available there is the right thing - maybe you don't wont to do semantic analysis against the current context, but rather against the context in some other module, etc |
21:45:16 | Araq | well I suggest to remove these features as they seem to be unsound |
21:46:32 | Araq | the evaluation shouldn't depend on the context/symbol table |
21:46:32 | Araq | symbol lookup needs to happen before |
21:46:32 | Araq | it might be that 'is' doesn't really depend on PContext but just some sane parts of it |
21:46:49 | Araq | but I haven't made such an analysis yet |
21:47:37 | Araq | and "compiles" is just one big misfeature on its own |
21:47:50 | zahary | my thinking is more along the lines of making the contexts more persistent (or the same parts of them) - this is related to other problems I have with generics instantiations (that need to be compiled as if their module is currently active) |
21:47:57 | * | brson joined #nimrod |
21:47:58 | Araq | the new generics should handle most sane use cases |
21:48:03 | zahary | the sane parts |
21:50:21 | Araq | I still think your way to deal with generics is inherently flawed ;-) |
21:50:42 | Araq | the instantiation doesn't belong to its original module |
21:50:54 | Araq | it belongs to the module that instantiates it |
21:50:55 | zahary | didn't I convince you each time we talk about it and then you forget about it :) |
21:51:04 | Araq | perhaps :P |
21:52:31 | Araq | but my way worked with symbol files |
21:52:40 | Araq | I had tests for it |
21:52:52 | zahary | where the generics go is not the whole story here - you want the proper scope, active module code generation flags, etc |
21:55:20 | Araq | no, you can't really say that. both using instantation scope or definition scope make sense for the flags |
21:56:39 | Araq | and arguably the {.push.} stuff is just wrong, C#'s "checked" environment is cleaner |
21:57:29 | zahary | I cannot recall now all arguments, but I have a pretty long list - you want the compile-time variables that the generic can modify for example to be remembered in its own module |
21:58:12 | Araq | so give me that list again please |
22:01:29 | zahary | first of all, if the generic is not reference counted, there is a hazard for wrong code generation - |
22:01:29 | zahary | it goes like this: |
22:01:29 | zahary | 1) module A is the first user of a generic X (side effects of generic instantiation are applied) |
22:01:29 | zahary | 2) module B uses the generic and compiler is happy to give module's A symbol as extern |
22:01:29 | zahary | 3) module A is recompiled with new code that doesn't use the generic |
22:01:30 | zahary | 4) the side-effects are undone and the extern definition in B is now dangling |
22:01:49 | zahary | so, the first thing I want is to reference count the generic in its own module |
22:02:24 | zahary | now, the pre-pass of generics have the known "late variable" problem |
22:02:56 | zahary | we can solve this by fully compiling the generic on the fly (but to do this we need to keep its original scope and environment arount) |
22:03:00 | zahary | around |
22:03:39 | zahary | we can argue just how much "environment" there is, but having its module alive will at least allow us to choose on a case-by-case basis |
22:06:08 | Araq | the hazard is exactly the hazard that dead code elimination produces and I wrote down how this is handled |
22:06:49 | zahary | you don't use a global cache, but that's not cool for me, because it doesn't have the guarantees that the static code inside the generic will be executed once |
22:08:07 | zahary | I want to have some strong guarantees for how compile-time variables will be handled |
22:08:23 | Araq | my implementation simply didn't use a global cache, yes. The issue however can be dealt with how dead code elimination is dealt with. I think. |
22:10:01 | zahary | where do .globals. from a generic go? again, currently pretty random |
22:10:35 | * | Demos_ quit (Read error: Connection reset by peer) |
22:10:56 | * | Demos_ joined #nimrod |
22:11:45 | zahary | the spec I propose is quite simple - the generic is treated as part of its own module and it's activated when the first user shows up and deactivated when the last user is gone |
22:13:49 | zahary | the current spec is "the first user gets to influence and be influenced by the generic in several ways; all other users either have no effect or are as well influenced depending on the compilation mode" |
22:15:41 | Araq | I can't see that. You want some really strong guarantees for what I consider an implementation detail: The merging of "compatible" instantiations. |
22:16:17 | Araq | where it's not clear what "compatible" means (I guess you mean "sameType" for every generic parameter) |
22:16:50 | Araq | the current spec has the problem that it does merge instantiations where it might not be sound |
22:17:20 | Araq | for instance if you have some overriden '==' for "int" which isn't even detected, but TSet[int] is simply reused instead |
22:17:47 | zahary | well, you may have noticed that I have several tests where I verify that a static: echo inside a generic will be executed once - this is my way of currently testing the guarantees I need |
22:18:22 | Araq | yes I noticed but I wonder if there is some other way to accomplish the same |
22:19:10 | Araq | and I know it's useful |
22:19:33 | zahary | this technique is widely popular in C++, but instead of static blocks, you use the equivalent of .global. variables MyPayload<T>::Value = SomePayload() |
22:20:00 | zahary | you get your code executed once per instantiation during the static initialization (which is a poor's man version of compile-time counters) |
22:20:25 | zahary | I have many libraries that depend on this trick |
22:20:36 | Araq | as I said, I know it's useful |
22:21:01 | Araq | but as you said, you rely on a side-effect of generic instantiation |
22:21:15 | Araq | which suggests there is a cleaner way to accomplish the same |
22:21:51 | Araq | I don't know an alternative yet |
22:21:57 | zahary | well, I've pondered on this question myself and generic instantiation is just a convenient case of memoization |
22:22:09 | Araq | yeah |
22:22:25 | Araq | and memoization across module boundaries is a hard problem |
22:22:42 | zahary | it's exactly the same problem if think about it |
22:22:56 | zahary | you can only transfer the complexity of maintaining the guarantees there |
22:23:05 | Araq | yes but for a start |
22:23:27 | zahary | and generics are quite a nice way to handle the problem as it's already intergrated with overload resolution and stuff like that |
22:23:45 | Araq | any solution that has the word "memoize" somewhere in its name is already a cleaner solution :P |
22:23:50 | zahary | "I want the side effect, because this type was used with function X" is very common pattern |
22:25:48 | zahary | any solution with more guarantees and simpler to understand spec is nicer than "we provide no guarantees how static code will be executed, when the .global. variables will go and so on" |
22:26:11 | zahary | * where the .global. * |
22:27:50 | Araq | well I'm not sure we provide no guarantees :P |
22:28:05 | Araq | we surely have no docs for it though |
22:28:20 | Araq | btw slightly different topic but |
22:28:41 | zahary | well, we don't have much guarantees if it depends on the compilation mode |
22:28:55 | Araq | what about {.global: 0..9.} to control the init section of the global? |
22:29:20 | zahary | is this per module or global? |
22:29:49 | Araq | I don't know, global globals are strange |
22:30:28 | Araq | the globals I am thinking of are all per module |
22:30:49 | Araq | otherwise it's some global not .global but .compileTime table ... er |
22:31:23 | Araq | var regexCache {.compileTime.}: TTable[string, TRegex] |
22:31:27 | zahary | I was planning to let the user designate his own function for initialising them (that can be called whereever you want), but they I came up with the newer spec that eliminates the confusing behavior IMO |
22:32:02 | zahary | but then * |
22:32:14 | Araq | the regexCache is the memoization thing again |
22:36:05 | Araq | btw .compileTime variables are now kepts between module compilations |
22:36:10 | Araq | *kept |
22:36:25 | zahary | what do you mean by "between"? |
22:36:35 | Araq | which breaks modularity but is what we need I guess |
22:36:57 | Araq | well a fresh PContext used to get a fresh set of compile time globals |
22:37:08 | Araq | now it's shared |
22:38:06 | Araq | which means we need to save them in a per project rodfile or something like that |
22:38:25 | zahary | my plan is a bit crazy, but I'm personally convinced it's the way forward. access to shared .compileTime. variables need to be restricted only to operations that have undoable semantics |
22:38:37 | zahary | increment/decrement add-to-set/remove-from-set, etc |
22:38:59 | Araq | and how does that help anything? |
22:39:03 | zahary | then you can have unloading/loading of a single module without the need to recompile the whole program |
22:39:38 | zahary | because you keep track of all the modifications done by this module and undo them when it's unloaded |
22:41:06 | dom96 | BitPuffin: ping |
22:44:40 | Araq | zahary: ok, sounds like a good plan. in fact, counters, sets and tables suffice, I think |
22:44:49 | Araq | nothing else is necessary |
22:45:42 | zahary | yes, me too. |
22:45:42 | zahary | the way it would work is to annotate the procs with an undo pragma |
22:45:42 | zahary | inc(x: var int, delta: int) {. undo: dec(x, delta) .} |
22:47:53 | Araq | nah that doesn't work |
22:48:17 | Araq | you need to track which numbers have been generated by what module |
22:48:34 | Araq | and then that module will get the same numbers later |
22:48:53 | Araq | I'm thinking of ID generation |
22:49:14 | Araq | 'dec' doesn't do the trick for that |
22:49:30 | zahary | yes, for ID generation you'll need some kind of free list |
22:50:10 | zahary | my remark was more about the fact that it's extendable by the user with these undo pragmas, but you're right that the basic counting will be often wrong |
22:50:28 | Araq | ok |
22:50:28 | Araq | I can see now how ordinary counters can work with 'dec' |
22:51:20 | Araq | well I don't think 'undo' helps |
22:51:57 | Araq | what helps is to special case 'var x {.compileTime.}: TTable[...]' etc. in the VM to track the module origins |
22:52:36 | Araq | then we can simply say a compile time error for: var x {.compileTime.}: UnsupportedType |
22:52:37 | zahary | I will simple build a list of closures (the undo expressions) that will be executed when the module is unloaded |
22:54:24 | Araq | again: how does this help? undo semantics are do not work for lots of cases |
22:55:06 | zahary | which case in particular? getID/returnID |
22:55:18 | zahary | counting is useful when you want the total of something in the program |
22:55:46 | Araq | another example: you register reserved words and then you generate names that must not be a reserved word |
22:55:47 | zahary | and I think there are no other ways besides keeping an undo list actually? |
22:56:14 | zahary | even if we only bless certain types, the implementation will still use undo-lists |
22:56:19 | Araq | then you unregister everything but the names already depended on that table |
22:56:20 | * | OrionPKM quit (Read error: Connection reset by peer) |
22:57:29 | * | darkf joined #nimrod |
22:58:39 | * | brson quit (Ping timeout: 240 seconds) |
22:59:08 | zahary | I think I understand your example, but the question is would it arise in practice. and what other scheme can you think of where unloading a single module is safe? |
23:00:13 | zahary | obviously, we can just give up and process the whole program again, but I think it's worth fighting |
23:01:57 | Araq | not sure, it's getting late. but you can argue for "aggregation" semantics |
23:02:29 | Araq | where you essentially say "compileTime" is just a shorthand for something you could implement via "gorge" |
23:02:36 | * | OrionPKM joined #nimrod |
23:03:04 | Araq | and what you can do easily with "gorge" is essentially to fill a database |
23:03:20 | Araq | and at some point empty that database again (full recompilation) |
23:03:42 | Araq | so you get really unique IDs for instance |
23:05:56 | * | zahary1 joined #nimrod |
23:06:20 | zahary1 | if you try to look at assigning IDs in a bit more general way, it's a category of problems where you gather some information by processing the code of the user |
23:06:29 | * | zahary quit (Read error: Connection reset by peer) |
23:07:22 | zahary1 | importing external information inside the program is the job for gorge/staticExec |
23:09:23 | Araq | well the argument goes like this: "I can already have my persistent storage solution via gorge. So the semantics of 'compileTime' globals should reflect that" (which also seems to me the easiest and most clean solution) |
23:10:23 | zahary1 | and what are the semantics of gorge (for the purposes of this discussion)? |
23:10:55 | Araq | well I have some simple .exe that uses sqlite in mind. |
23:11:46 | zahary1 | my point was that the compileTime variables don't merely store persistent information - they let you build up some data derived from your own code |
23:11:53 | * | brihat left #nimrod (#nimrod) |
23:13:07 | Araq | yes well, I argue it should be persistent *across* compiler invokations |
23:13:13 | zahary1 | i.e. "assign ID of all the types I sent over the network using the RPC library"; in jested, gather up all paths defined by the user and compile a composite regex matching all of them with a single DFA |
23:13:58 | Araq | so the DFA ends up containing artifacts of old code |
23:14:01 | zahary1 | I have myself asked for a persistent cache - this is just another use case |
23:14:08 | Araq | until you do --forceBuild |
23:14:55 | Araq | just like deadCodeElim + symbolFiles produces cruft, it's all the same problem |
23:15:10 | Araq | you live with the cruft and things are fine |
23:15:23 | Araq | the cruft ceases to exist with a full rebuild |
23:16:13 | Araq | and yes, that is the persistent cache you asked about |
23:16:18 | zahary1 | I think it's up to the user to pick the API - for example, I could use the persistent cache to remember things that were true about my program in the past - in a serialization library, I could bump a version number every time I add a new fields to an object - the cache could remember how an old version looked like |
23:16:56 | zahary1 | … so it could correctly build a new object from an old serialized blob |
23:17:41 | Araq | now that's something you should use 'gorge' for |
23:18:24 | Araq | I'm arguing the semantics of 'compileTime' should be: persistent across compiler invocations, since they are already persistent across modules |
23:18:53 | Araq | this seems to solve most problems immediately |
23:19:12 | zahary1 | and how are they rebuilt? do I bump the counter on each compilation (until I do a forceBuild)? |
23:19:27 | Araq | no that handles the compiler for you |
23:19:35 | zahary1 | how exactly? |
23:19:51 | Araq | the compiler stores&loads all globals in a project-wide .rod file |
23:20:18 | zahary1 | and let's say I modify a single module - what happens? |
23:20:27 | zahary1 | it contains code for bumping the counter |
23:20:45 | Araq | the counter's value is restored |
23:20:59 | zahary1 | restored to what? |
23:21:07 | Araq | just like in a REPL where the data remains persistent and yet the code can be changed |
23:21:32 | zahary1 | so it's bumped on each compilation (that's what would happen in a REPL) |
23:21:43 | zahary1 | we use once guards to prevent that |
23:21:49 | zahary1 | … when reloading script codes |
23:22:07 | Araq | if you recompile the part that increments it, then yes |
23:22:56 | zahary1 | well, as I said this is not very nice if you rely strongly on correct values |
23:23:28 | Araq | I'm not sure what "correct" means for you here |
23:24:18 | zahary1 | let's say you building the component system of fowl - you strongly rely on the number of component types and messages in order to build several vtable-like data structures |
23:24:54 | zahary1 | if the count gets elevated, your program is going to use more and more memory (even if that's not such a big issue, I could come up with a more critical dependency on correctness) |
23:26:17 | Araq | ok so you essentially argue for minimal counter values |
23:26:27 | zahary1 | for precise counter values |
23:27:40 | Araq | alright well I'm out of ideas then |
23:28:05 | zahary1 | you are building luabind - there is a list of types that must be registered in lua - this list must be maintained precisely, because if you keep an older type that is no longer around, you won't be able to compile the code |
23:28:40 | zahary1 | for all practical problems that I've needed compile-time variables in C++, the undo semantics suffice to solve the problem |
23:29:38 | gcr | Is it possible to unpack an array? |
23:31:09 | Araq | gcr: I don't think so. it's a template/macro away though |
23:31:18 | gcr | Hm, ok |
23:33:58 | Araq | zahary1: the "undo" semantics are not correct for the obvious implementation of getID(). What's your proposed solution for that? |
23:35:58 | zahary1 | I have two solutions - getID/returnID backed by a free-list; addToOrderedSet/removeFromOrderedSet with stage two assigning the IDs from the order in the final set (this is important, because you want two different compilation of the program to have the same IDs if they are going to talk over the network) |
23:37:13 | zahary1 | I haven't covered this "stage two" in the discussion so far, but it's a proc that you assign to the variable to be executed when all the gathering of information is complete |
23:41:46 | Araq | so ... this sounds rather horrible :-) |
23:42:35 | zahary1 | it's no coincidence that they often call generative programming "multi-stage programming" |
23:42:50 | Araq | instead of some explicit mapping like {modA.TypeA: 1, modB.TypeB: 4} # gap for compatibility |
23:42:59 | zahary1 | there are no simple solutions to these complicated problems, but at least there are solutions |
23:43:06 | Araq | you rather let the compilation stage produce that? |
23:43:30 | zahary1 | the explicit mapping doesn't compose, because it has to be centralized |
23:43:37 | Araq | yes |
23:43:41 | zahary1 | you cannot have a library that adds just 3 new RPCs |
23:43:59 | zahary1 | so it's worth pursuing the automated multi-stage solution |
23:45:24 | Araq | well GUIDs do compose but are too inefficient |
23:45:34 | zahary1 | yes |
23:48:01 | Araq | I can't see this ever working. The gap comes from 2 types that existed but have been removed. How can the compilation ever determine this? |
23:49:16 | Araq | the compiler happily assigns 2 to TypeB which is more "precise" according to you, but wrong for interop |
23:49:21 | gradha | gcr: example https://gist.github.com/gradha/8140318 |
23:49:22 | zahary1 | well, the networked scenario I described requires that both systems are built from the same source (the same set of types) |
23:50:33 | zahary1 | you can have the ordering to be chronological - then introducing new types become possible against an older server, but I haven't done this in C++ |
23:52:06 | Araq | gradha: shouldn't that be 'parseExpr'? |
23:52:11 | zahary1 | in C++, I have successfully used alphabetic ordering, generated with the .globals. tricks - the systems error out immediately if their sets don't match (there is a checksum of the set that is present in the handshake) |
23:52:23 | gradha | Araq: no idea, it works though |
23:52:59 | Araq | you got impressive macro skillz :-) |
23:53:26 | gradha | I'm sure you can improve with quoting |
23:53:47 | gradha | so maybe the parseStmt won't work in the new vm? |
23:53:52 | Araq | nah, I never use quoting |
23:54:54 | Araq | parseStmt shouldn't work I guess. the compiler should enforce a 'void' context for that which means the compiler ends up complaining about a missing 'discard' |
23:55:37 | Araq | but I consider 'parseExpr' in a macro to be a serious design flaw |
23:56:09 | Araq | if building strings ends up being easier than using the API properly the API has failed |
23:57:21 | gradha | sorry, couldn't be bothered to look up the AST for subscript notation |
23:58:15 | Araq | well that's exactly my point |
23:59:55 | gcr | gradha: dude, thanks! |