--- Log opened Thu May 27 00:00:29 2010 |
00:21 | | Reiv[Graduate] [orthianz@Nightstar-22771ff8.xnet.co.nz] has joined #code |
00:26 | | You're now known as TheWatcher[T-2] |
00:29 | | You're now known as TheWatcher[zZzZ] |
00:32 | | Derakon[AFK] is now known as Derakon |
00:44 | | Thaqui [Thaqui@27B34E.D54D49.F53FA1.6A113C] has joined #code |
01:38 | | gnolam [lenin@Nightstar-38637aa0.priv.bahnhof.se] has quit [[NS] Quit: Z?] |
01:55 | | AnnoDomini [annodomini@Nightstar-70e08728.adsl.tpnet.pl] has quit [[NS] Quit: Peels.] |
02:00 | | Reiv[Graduate] [orthianz@Nightstar-22771ff8.xnet.co.nz] has quit [Connection reset by peer] |
02:15 | | Reiv[Graduate] [orthianz@Nightstar-2d24cd24.xnet.co.nz] has joined #code |
03:01 | < celticminstrel> | Searching through the __dict__ probably isn't the best way to do this, but it's better than having a giant if...elif...elif...elif in a function... then again, having a dictionary of callback functions would work too... |
03:01 | <@ToxicFrog> | Dictionary of callbacks plz |
03:02 | <@Vornicus> | <3 dictionaries |
03:08 | < celticminstrel> | It's only slightly easier to use the class's internal dictionary, so dictionary of callbacks would be fine; but then would I have to pass the self parameter explicitly? |
03:10 | < celticminstrel> | The (albeit slight) advantage to examining the class's dictionary is that I can simply define a new member function with the chosen naming convention and it will "automatically work". |
03:10 | < celticminstrel> | Whereas with the callback dictionary I need to both define it and add it to the dictionary. |
03:10 | <@Derakon> | Celticminstrel: you can do {'foo': self.processFoo} and not have to pass "self" around. |
03:11 | < celticminstrel> | Ah, that looks like it could be what I would want... |
03:20 | <@ToxicFrog> | Derakon: auto-closing of methods? Sweet. |
03:39 | <@Derakon> | TF: yeah, I do it all the time at work for dialog event handlers. |
03:39 | <@Derakon> | self.onClick, etc. |
04:22 | | Vornicus [vorn@ServerAdministrator.Nightstar.Net] has quit [[NS] Quit: ] |
04:24 | | Vornicus [vorn@ServerAdministrator.Nightstar.Net] has joined #code |
04:24 | | mode/#code [+o Vornicus] by Reiver |
05:08 | | celticminstrel [celticminstre@Nightstar-f8b608eb.cable.rogers.com] has quit [[NS] Quit: *whistles* Did you hear something?] |
05:42 | <@ToxicFrog> | \o/ |
05:42 | <@ToxicFrog> | All I need is xchat_hook_server, xchat_hook_print, and xchat_plugingui_* |
05:43 | <@ToxicFrog> | And maybe xchat_gettext, although I'm wary of binding undocumented functions. |
05:43 | <@ToxicFrog> | xchat_hook_fd stays unbound because I can't think of a way to bind it that isn't horribly unsafe. |
05:44 | <@Derakon> | Why are you writing an IRC bot? |
05:44 | <@ToxicFrog> | I'm not (yet). |
05:44 | <@ToxicFrog> | I'm writing a Lua plugin for xchat so I can finally replace this utility DSO I've been carting around since xchat 2.2. |
05:50 | <@ToxicFrog> | Once I'm done that I probably will port my old mapbot from its (terrible) coroutine-based framework to xchat-text. |
06:36 | | ToxicFrog [ToxicFrog@ServerAdministrator.Nightstar.Net] has quit [Operation timed out] |
06:39 | | SmithKurosaki [Smith@Nightstar-26933809.dsl.teksavvy.com] has quit [Ping timeout: 121 seconds] |
06:43 | | Derakon is now known as Derakon[AFK] |
06:44 | | SmithKurosaki [Smith@Nightstar-5e45a1c6.dsl.teksavvy.com] has joined #code |
06:46 | | ToxicFrog [ToxicFrog@ServerAdministrator.Nightstar.Net] has joined #code |
06:46 | | mode/#code [+o ToxicFrog] by Reiver |
07:38 | | ToxicFrog [ToxicFrog@ServerAdministrator.Nightstar.Net] has quit [Operation timed out] |
07:39 | | Orth [orthianz@Nightstar-68f66f01.xnet.co.nz] has joined #code |
07:40 | | SmithKurosaki [Smith@Nightstar-5e45a1c6.dsl.teksavvy.com] has quit [Ping timeout: 121 seconds] |
07:41 | | Reiv[Graduate] [orthianz@Nightstar-2d24cd24.xnet.co.nz] has quit [Ping timeout: 121 seconds] |
07:41 | | ToxicFrog [ToxicFrog@ServerAdministrator.Nightstar.Net] has joined #code |
07:41 | | mode/#code [+o ToxicFrog] by Reiver |
07:41 | | SmithKurosaki [Smith@Nightstar-0a57481d.dsl.teksavvy.com] has joined #code |
08:46 | | Orth [orthianz@Nightstar-68f66f01.xnet.co.nz] has quit [Client closed the connection] |
08:52 | | Reiv[Graduate] [orthianz@Nightstar-68f66f01.xnet.co.nz] has joined #code |
08:58 | | You're now known as TheWatcher |
09:15 | | Reiv[Graduate] [orthianz@Nightstar-68f66f01.xnet.co.nz] has quit [Connection reset by peer] |
09:19 | | AnnoDomini [annodomini@Nightstar-70e08728.adsl.tpnet.pl] has joined #code |
09:20 | | mode/#code [+o AnnoDomini] by Reiver |
09:21 | | Reiv[Graduate] [orthianz@Nightstar-68f66f01.xnet.co.nz] has joined #code |
09:58 | | Tarinaky [Tarinaky@Nightstar-b613f47a.adsl.virginmedia.net] has quit [Ping timeout: 121 seconds] |
10:11 | | Tarinaky [Tarinaky@Nightstar-9b0dcd91.adsl.virginmedia.net] has joined #code |
10:12 | | Rhamphoryncus [rhamph@Nightstar-bbc709c4.abhsia.telus.net] has quit [Client exited] |
11:12 | | gnolam [lenin@Nightstar-38637aa0.priv.bahnhof.se] has joined #code |
11:14 | | Reiv[Graduate] [orthianz@Nightstar-68f66f01.xnet.co.nz] has quit [Connection reset by peer] |
11:21 | | Reiv[Graduate] [orthianz@Nightstar-68f66f01.xnet.co.nz] has joined #code |
11:35 | | Vornicus is now known as Vornicus-Latens |
11:51 | | Thaqui [Thaqui@27B34E.D54D49.F53FA1.6A113C] has quit [Client closed the connection] |
12:01 | | Reiv[Graduate] [orthianz@Nightstar-68f66f01.xnet.co.nz] has quit [Connection reset by peer] |
12:08 | | Reiv[Graduate] [orthianz@Nightstar-68f66f01.xnet.co.nz] has joined #code |
12:16 | | Reiv[Graduate] [orthianz@Nightstar-68f66f01.xnet.co.nz] has quit [Connection reset by peer] |
12:22 | | Reiv[Graduate] [orthianz@Nightstar-68f66f01.xnet.co.nz] has joined #code |
14:39 | | Tarinaky [Tarinaky@Nightstar-9b0dcd91.adsl.virginmedia.net] has quit [Operation timed out] |
14:55 | | Tarinaky [Tarinaky@Nightstar-70878730.adsl.virginmedia.net] has joined #code |
15:30 | | Reiv[Graduate] [orthianz@Nightstar-68f66f01.xnet.co.nz] has quit [Ping timeout: 121 seconds] |
15:39 | | PinkFreud is now known as PinkCoffeeZombie |
15:43 | | celticminstrel [celticminstre@Nightstar-f8b608eb.cable.rogers.com] has joined #code |
16:49 | | Reiv[Graduate] [orthianz@Nightstar-41c10dd9.xnet.co.nz] has joined #code |
16:54 | | Tarinaky [Tarinaky@Nightstar-70878730.adsl.virginmedia.net] has quit [Operation timed out] |
17:08 | | Tarinaky [Tarinaky@Nightstar-1c1774a2.adsl.virginmedia.net] has joined #code |
17:30 | | Reiv[Graduate] is now known as Reivles |
17:34 | | Derakon [Derakon@Nightstar-1ffd02e6.ucsf.edu] has joined #code |
17:34 | | mode/#code [+o Derakon] by Reiver |
17:34 | <@Derakon> | Morning, folks. |
17:42 | | Attilla [Attilla@Nightstar-c56d6882.threembb.co.uk] has joined #code |
17:42 | | mode/#code [+o Attilla] by Reiver |
18:07 | | AbuDhabi [annodomini@Nightstar-9440674e.adsl.tpnet.pl] has joined #code |
18:08 | | AnnoDomini [annodomini@Nightstar-70e08728.adsl.tpnet.pl] has quit [Ping timeout: 121 seconds] |
18:18 | | Derakon [Derakon@Nightstar-1ffd02e6.ucsf.edu] has quit [[NS] Quit: Leaving] |
18:32 | | Rhamphoryncus [rhamph@Nightstar-bbc709c4.abhsia.telus.net] has joined #code |
18:38 | < celticminstrel> | Ghosting automatically changes your nickname, right? |
18:38 | < Tarinaky> | No. |
18:38 | < Tarinaky> | Not unless the server's weird or your client is. |
18:39 | < celticminstrel> | Oh. Well, never mind then. |
18:41 | < celticminstrel> | When a nickname is already in use, is it the client that automatically selects a different one? |
18:41 | < Tarinaky> | Yes. |
18:42 | < celticminstrel> | So, response to 433 should be "choose different nick, ghost, change nick". |
18:50 | < celticminstrel> | ...so, does 451 mean that a successful NICK command has yet to be sent? Or that a USER command has not been sent? Or does it mean that the nick has not been registered with NickServ? I was assuming the latter, but now I'm thinking that's likely not the case... |
18:52 | <@ToxicFrog> | celticminstrel: well, if you read the RFC, you should note three things: |
18:52 | <@ToxicFrog> | - 451 is described as ERR_NOTREGISTERED |
18:52 | < celticminstrel> | Yes. |
18:52 | <@ToxicFrog> | - NickServ is not mentioned anywhere in the RFC, but |
18:53 | <@ToxicFrog> | - there is a section named "Connection Registration" |
18:53 | < celticminstrel> | Ooh, okay. The assumption about NickServ, by the way, was before I actually looked it up in the RFC. |
18:57 | | Kazriko [kaz@Nightstar-e09690fa.client.bresnan.net] has quit [Ping timeout: 121 seconds] |
18:57 | < celticminstrel> | Supposedly NICK is supposed to be sent before USER, but it seems to work the other way round as well. |
18:58 | < celticminstrel> | Which is a good thing, really. |
18:59 | < celticminstrel> | ...and this library send PASS last of all despite the RFC saying it must be sent first. Lovely. Good thing I don't need PASS. |
18:59 | < celticminstrel> | ^sends |
19:08 | <@ToxicFrog> | IIRC, the RFC says that NICK and USER are allowed in any order, but that NICK is recommended first |
19:09 | | Vornicus-Latens is now known as Vornicus |
19:10 | < celticminstrel> | I think it said NICK first was required... but only between servers, I guess. |
19:11 | < celticminstrel> | Which a client/bot doesn't care about. |
19:12 | <@ToxicFrog> | Yes. |
19:13 | < Namegduf> | NickServ isn't in the RFC in any form; connection registration refers to providing a nick and such to be connected, and is unrelated to Services registration. |
19:13 | < celticminstrel> | I did read that section after you pointed me to it. :) |
19:13 | < Namegduf> | Services is an external program utilising the protocol and not taken account of within it, as a whole. |
19:14 | < celticminstrel> | Are the services at all standardized? They seem to be slightly different on all the networks I frequent... |
19:14 | < Namegduf> | No. |
19:14 | < celticminstrel> | I'm feeling an urge to improve this library, for some reason. |
19:15 | < celticminstrel> | ^ sorry, TF pointed me to it, not you. |
19:15 | < Namegduf> | There's some "IRCv3" extensions which do add standardised things |
19:15 | < Namegduf> | Such as SASL authentication during connection registration. |
19:16 | < celticminstrel> | For some reason, the base class doesn't even pong. Sure, there's a second subclass that does, but why would anyone want a class that doesn't pong? |
19:17 | < Namegduf> | Sounds like they're obsessed with subdividing functionality between classes that inherit from each other. |
19:19 | < celticminstrel> | They search the class dictionary to see if a callback is defined for a particular response, rather than providing stubs for every possible response. I dunno whether that's really bad, but the "Rethink this, seriously" comment suggests that there could be a better way to do it. (And while providing stubs sounds like it'd work, it's also probably not the best way since that means you'd have hundreds of stub methods.) |
19:20 | <@ToxicFrog> | Yeah, personally, I think 'search the object for a method with this name, none found? skip" is better than stubbing everything out |
19:20 | <@ToxicFrog> | Or providing a dictionary of callbacks as a data member. |
19:20 | < celticminstrel> | True, it could provide a "register callback" interface or something, I suppose... |
19:21 | < celticminstrel> | A little more work for the extender, then, but not that much. |
19:21 | <@ToxicFrog> | You wouldn't even need that; self.callbacks["ping"] = \x -> send ("pong "..x) |
19:22 | < celticminstrel> | ...what? |
19:22 | <@ToxicFrog> | ...what? |
19:22 | <@ToxicFrog> | I'm pretty sure that's not legal python but I thought it got the idea across :/ |
19:22 | < celticminstrel> | It does, yeah; I suppose you're suggesting something like lambdas? |
19:23 | < celticminstrel> | self.callbacks["ping"] = lambda x: send("pong " + x); |
19:24 | <@ToxicFrog> | Yeah. |
19:24 | | * ToxicFrog kind of ended up with a bastardized hybrid of python, haskell, and lua there~ |
19:24 | < celticminstrel> | Hehe. |
19:25 | < Namegduf> | The issue there is that you could onyl have one callback. |
19:25 | < Namegduf> | A user adding their own callback for ping would turn off ping replies. |
19:25 | < Namegduf> | "whoops" |
19:25 | <@ToxicFrog> | Yeah. But providing methods has the same problem. |
19:26 | < Namegduf> | Yeah, but that's why you might want to "rethink" the way it is. |
19:26 | <@ToxicFrog> | xchat uses a callback-registration approach, where the callbacks run in reverse order of registration and can 'eat' the event |
19:26 | < celticminstrel> | Well, maybe that could be solved by making 'callbacks' a dictionary-like utility class rather than an actual dictionary... |
19:26 | <@ToxicFrog> | Preventing later callbacks, xchat's internal handlers, both, or neither from seeing the event. |
19:27 | < celticminstrel> | The thought just popped into my head of using exceptions to "eat" callbacks. <_< |
19:27 | < celticminstrel> | ^um, events, sorry |
19:29 | <@ToxicFrog> | "using events to eat callbacks"? |
19:30 | < celticminstrel> | ? |
19:30 | <@ToxicFrog> | Just wondering what you meant by that. |
19:30 | < celticminstrel> | Using exceptions to eat events. 9_9 |
19:30 | <@ToxicFrog> | Aah. |
19:30 | < celticminstrel> | Oh, I see you must've misinterpreted my correction. Sorry. |
19:31 | <@ToxicFrog> | ...so every function would end with 'raise irc.EventHandlerEatNoneException' or something? |
19:31 | <@ToxicFrog> | Sounds...messy. What's wrong with return? |
19:33 | < celticminstrel> | Nothing, I guess. |
19:33 | < Tarinaky> | Exceptions are, be definition, messy. |
19:33 | < celticminstrel> | To be honest, they're probably about equivalent, at least in terms of neatness of code. |
19:33 | < Tarinaky> | My understanding is they're best used to handle exceptional behavior. |
19:33 | < celticminstrel> | So, might as well just use return then. |
19:34 | < celticminstrel> | I said the idea popped into my head; I never said it was a good idea. :P |
19:43 | < Rhamphoryncus> | IRC is a bastard protocol. It will resist all attempts of *good* code organization |
19:45 | < Rhamphoryncus> | Rather than exceptions you could consider a singleton. Python has a NotImplemented singleton returned by certain operator methods |
19:46 | <@ToxicFrog> | Rhamphoryncus: a good framework can hide a lot of that, though. |
19:46 | <@ToxicFrog> | Also, the discussion isn't implemented vs not implemented |
19:46 | < Namegduf> | There's a non-crack way to do this. |
19:46 | <@ToxicFrog> | It's "after this callback runs, should other callbacks be allowed to see this event" |
19:46 | < Namegduf> | You can return *a value* |
19:46 | < Namegduf> | To indicate this kind of thing |
19:46 | <@ToxicFrog> | Namegduf: yes, that's what I suggested |
19:46 | < Namegduf> | This is how InspIRCd module hooks work |
19:47 | <@ToxicFrog> | That's how xchat hooks work, that's how insp hooks work, that's how most sane event-handling callback systems work. |
19:47 | < Rhamphoryncus> | Aye, I'm not suggesting you use NotImplemented (except maybe for for a stub). What I mean is created your own like EatEvent |
19:47 | < Rhamphoryncus> | I really hate how gtk has you return true/false all the time. Maybe it's the best option in C, but in python it's unnecessarily vague |
19:48 | < Rhamphoryncus> | Even C could use an enum |
19:51 | | * ToxicFrog nods |
19:52 | < Tarinaky> | I thought enums were a C++ feature? |
19:52 | < Tarinaky> | The C equiv would be #defines |
19:52 | < Rhamphoryncus> | Nope, C has them too |
19:53 | < celticminstrel> | Yep. |
19:53 | < celticminstrel> | ...how is a singleton better than a constant? |
19:53 | < Tarinaky> | Singletons allow you to control the order of initialisation. |
19:54 | < Tarinaky> | Constants do not. |
19:54 | < celticminstrel> | Initialization of what now? |
19:54 | < Tarinaky> | The constant/singleton's contents. |
19:54 | < Rhamphoryncus> | But they're rarely used because.. well, C is stupid, heh. Maybe because the type it creates isn't too obvious and because they often do mixing of bitfields where you really want defines |
19:54 | < Rhamphoryncus> | Tarinaky: wrong kind of singleton. You're thinking of "OMG I'm not a global, honest!" |
19:54 | < Tarinaky> | Rhamphoryncus: Oh. Misread, sorry. |
19:55 | < Rhamphoryncus> | Tarinaky: I'm talking about a dummy value who's identity is the only thing meaningful, like None |
19:55 | < Tarinaky> | Rhamphoryncus: What's this kind of singleton? |
19:56 | < celticminstrel> | ^ whose! "who's" means "who is"! |
19:56 | < Rhamphoryncus> | celticminstrel: the real point is so that you can say "return EatEvent" (or whatever). It's explicit. Although you could define it as "EatEvent = 7", that's unnecessary and may lead to people hardcoding 7. Better to use "EatEvent = object()" (or define your own class so it gets named) |
19:56 | < Rhamphoryncus> | celticminstrel: boo :P |
19:57 | < celticminstrel> | So, either use 'EatEvent = object()', or use 'class EatEvent: pass'? |
19:57 | < Rhamphoryncus> | or 'class EatEventType(object): pass; EatEvent = EatEventType()' |
19:58 | | * Rhamphoryncus blames the english language for being stupid about possession |
19:58 | < celticminstrel> | Very true. 9_9 |
19:59 | < Rhamphoryncus> | I can honestly say I've never seen "who's vs whose" mentioned before. Even on those pages talking about proper use of possession |
20:00 | < celticminstrel> | That last example seems a bit more than necessary; a user could return EatEventType instead of EatEvent. |
20:00 | < celticminstrel> | And... wow, re |
20:00 | < celticminstrel> | ally? |
20:01 | < Rhamphoryncus> | Well, arguably it should be _EatEventType to indicate privacy |
20:01 | < Rhamphoryncus> | aaand to get more complicated you could override __new__ to ensure further instantiation doesn't happen |
20:02 | < Rhamphoryncus> | It starts to get pretty silly though |
20:03 | <@ToxicFrog> | Or you could just return a string~ |
20:04 | < Namegduf> | What the hell is going on |
20:04 | < Namegduf> | When I looked away people were talking about enums, well and good |
20:04 | < Namegduf> | But when I look back its this overengineered stuff to simply return a constant. |
20:05 | < Namegduf> | If the language can't do type-safe enums, which Python can't because it doesn't enforce type-safety, a string is pretty much equivalent, yeah. |
20:07 | < celticminstrel> | Gah, lag from Chrome-hang. |
20:07 | < celticminstrel> | So, which is better? The class, or the string? |
20:08 | < Rhamphoryncus> | Namegduf: strings encourage people to use the string as the constant, which is error prone |
20:08 | < Namegduf> | Rhamphoryncus: No more error prone than anything else in non-typesafe languages |
20:09 | < Rhamphoryncus> | I do use strings when I've got several modes to track, but when I'm returning just one possible value? I'd rather it be named |
20:09 | < Namegduf> | You do have several values. |
20:09 | < Namegduf> | If you only had one value, it'd be equivalent to no return value. |
20:09 | < Rhamphoryncus> | None vs EatEvent? |
20:09 | < Namegduf> | Right. |
20:09 | < Rhamphoryncus> | arguable |
20:09 | <@ToxicFrog> | Or EatEventAll vs EatEventPlugins vs None |
20:09 | < Namegduf> | You could just define EatEvent = 1 |
20:10 | < celticminstrel> | Huh? |
20:10 | < Namegduf> | Or something |
20:10 | < celticminstrel> | What's the difference between those two? |
20:10 | < Namegduf> | Not a class, just a constant global variable. |
20:10 | <@ToxicFrog> | Or let's go the whole hog, have it return a function that when passed a callback will return true if the callback is allowed to see it and false otherwise! |
20:10 | < Rhamphoryncus> | problem there is you go to print it out and you just get 1, rather than EatEventAll |
20:10 | < celticminstrel> | ...um, what, ToxicFrog? |
20:10 | < Namegduf> | Why would you be printing it out? |
20:10 | < Rhamphoryncus> | debugging |
20:11 | < Namegduf> | Why is this such a significant usecase as to warrant additional complexity in the software? |
20:11 | < celticminstrel> | What about just EatEvent = 'EatEvent'? |
20:11 | < Rhamphoryncus> | *shrug* |
20:11 | < Namegduf> | That sounds like it'd work, too, despite looking funny. |
20:12 | < celticminstrel> | What, the thing I posted? |
20:12 | < Namegduf> | Yeah. |
20:12 | < Rhamphoryncus> | maybe EatEvent = '_EatEvent' to indicate the string is private? |
20:12 | < celticminstrel> | I dunno how that'd make much difference. |
20:12 | < Rhamphoryncus> | it's slight, yes |
20:17 | < Rhamphoryncus> | I should have commented on composing handlers instead. Much more interesting subject |
20:22 | < Rhamphoryncus> | inheritance is inadequate, but callbacks are crude. They're just a mechanism, with no suggestion of what's the correct thing to do |
20:24 | < celticminstrel> | Huh? |
20:37 | < Rhamphoryncus> | Replacing a dummy default callback is one thing, but a callback provided by another plugin? That's got to be wrong |
20:38 | < celticminstrel> | ... |
20:39 | < Rhamphoryncus> | Similar problem with multiple inheritance. Two unrelated classes providing the same method? There is no correct choice on which method should be dominant. It's just wrong. |
20:40 | < Namegduf> | There's a simple solution, really |
20:40 | < Namegduf> | Forbid multiple inheritance where methods overlap. |
20:40 | < Rhamphoryncus> | Namegduf: aye, that's my general opinion |
20:41 | < Tarinaky> | Multiple inheritance - especially public inheritance - should only occur in a small number of cases anyway. :/ |
20:41 | < Namegduf> | Alternatively, you could require that your class doing the multiple inheritance overrides the method. |
20:41 | < Namegduf> | And implements what should be done. |
20:41 | < Namegduf> | Again simple, but much less restrictive. |
20:43 | < Rhamphoryncus> | I'm kinda curious about how to avoid using inheritance, ever. Replace it with mixins, composition, and interfaces (or ABCs) |
20:44 | | * Namegduf has never had trouble in languages without inheritance |
20:44 | < Namegduf> | Interfaces provide valuable abstraction, and composition can be a useful tool. |
20:44 | < Rhamphoryncus> | I've never used one in a serious fashion. Maybe C, but it doesn't count |
20:44 | < Namegduf> | It doesn't? |
20:45 | < Rhamphoryncus> | C doesn't provide most of the other features common to OO like GC, methods, and operator overloading |
20:45 | <@McMartin> | C counts for composition, but not inheritance. |
20:46 | <@McMartin> | "It doesn't count unless the compiler knows about it" is the basic principle here, I think. |
20:46 | <@McMartin> | You can of course build a coding discipline that acts *like* inheritance. |
20:46 | <@McMartin> | But if you allow that, then hand-writing hexadecimal machine code is actually logic programming just like Prolog is. |
20:47 | < Namegduf> | McMartin: I think you missed the "without" part |
20:47 | < Rhamphoryncus> | I do mixins and composition in python (and arguably most base classes serve as mere mixins anyway) |
20:47 | < Namegduf> | Rhamphoryncus: I didn't realise you were restricting yourself to OO languages. |
20:48 | < Namegduf> | I'll agree that C isn't one. |
20:48 | < Rhamphoryncus> | Namegduf: classes tend to be linked with OO :) |
20:48 | < Namegduf> | Rhamphoryncus: I had no idea you were restricting yourself to classes. |
20:49 | < Rhamphoryncus> | inheritance tends to refer to classes? |
20:49 | < Namegduf> | Yes, and you said "without" it. |
20:49 | < Namegduf> | You didn't say "without inheritance but still with classes", I misunderstood, sorry. |
20:49 | < Namegduf> | Anyways, I've found myself not to miss inheritance when not available, except as a way of creating abstract interfaces. |
20:49 | < Rhamphoryncus> | My intent was "given what classes are used for, I wonder about using X instead..." |
20:50 | < Namegduf> | Leading to "fun" things in C sometimes |
20:50 | < Rhamphoryncus> | C doesn't use classes in such a fashion to begin with, so it's not comparable |
20:51 | < Namegduf> | So... you're wondering if you can emulate design patterns for inheritable classes using these other features, rather than implement similar functionality differently? |
20:52 | < Rhamphoryncus> | And how much common usage actually matches the inheritance pattern, rather than a mixin or composition |
20:52 | < Namegduf> | Ah. |
20:53 | < Rhamphoryncus> | For instance, a single abstract base class with many direct subclasses, none of which are further subclassed. The base class is never instantiated. That's just a mixin |
20:56 | < Rhamphoryncus> | I have a file like that right now. 15 subclasses and an simple base class. There was actually actually a second abstract base class, a subclass of the first, but it was refactored out |
20:58 | < Rhamphoryncus> | That's where it gets a little hazy, treating python as just mixins and composition. That second base class fits more clearly as inheritance of a mixin, otherwise it wouldn't still be a "mixin type" (conceptually) |
21:04 | < Rhamphoryncus> | That's assuming I modify the language to have either a normal class (which can be instantiated and can have mixins) or a mixin (which can't). The naive approach fails for that reason. I could think up ways to get it to work, but I'd like to examine how other languages in similar situations handled it |
21:05 | | Attilla_ [Attilla@Nightstar-27696e15.threembb.co.uk] has joined #code |
21:06 | < Rhamphoryncus> | If I were to allow mixins to include other mixins that'd effectively be inheritance, but conflicts wouldn't be allowed, no type checking would be included by default, and normal classes would default to "final" (in the java sense, cannot be further subclassed) |
21:07 | < Rhamphoryncus> | instantiation would also have to be redesigned, since that's the major use case for cooperative super calls |
21:07 | | Attilla [Attilla@Nightstar-c56d6882.threembb.co.uk] has quit [Ping timeout: 121 seconds] |
21:08 | | Attilla_ is now known as Attilla |
21:09 | < Rhamphoryncus> | Defaulting to final would have big consequences, and is undesirable for a language like Python, but I feel really uncomfortable about subclassing a class that was never designed for it, ya know? |
21:11 | < Rhamphoryncus> | Python didn't originally allow subclassing of list/str/dict, and added it later, but oops 90% of the methods are done directly in C and use only the base class's versions, so you can't override them anyway |
21:12 | < Rhamphoryncus> | why? Because there's all sorts of hidden assumptions. They're used internally by the class itself. It couldn't use them that way if they could be overridden |
21:12 | < celticminstrel> | Why not? |
21:13 | < Rhamphoryncus> | I'd have to dig around to find specific examples. Mostly it's just the nature of C though. They're designed collectively |
21:13 | < Rhamphoryncus> | Heck, half of them aren't even public functions. They're common helper functions |
21:14 | < Rhamphoryncus> | Even though conceptually two methods may be equivalent, neither calls each other through a public interface |
21:15 | <@ToxicFrog> | I suspect it's something like: method foo maps to C function py_foo; method bar maps to py_bar |
21:16 | <@ToxicFrog> | Foo calls bar. |
21:16 | < Rhamphoryncus> | Maintaining that, rather than redesigning it to use a hierarchy over which public methods you should override to affect other public methods, leads you to composition |
21:16 | < Rhamphoryncus> | yup |
21:16 | <@ToxicFrog> | However, the way this is implemented, foo calls py_bar() rather than going back out into python to call self.bar |
21:16 | <@ToxicFrog> | So if you redefine bar in python, too bad, the original version of foo is still calling the C version of bar directly. |
21:16 | < Rhamphoryncus> | exactly |
21:19 | < Rhamphoryncus> | So, even if you did allow some public methods to be overridden in a well defined fashion, what you'd end up with is mixin+composition. The core parts are kept isolated and don't care what you think. The public parts are just a mixin |
21:22 | < Rhamphoryncus> | A true subclass wouldn't distinguish a base's public from private. It would access both just as easily, and wouldn't violate any assumptions because it would be designed at the same time as the base |
21:22 | < Rhamphoryncus> | By the same person too |
21:25 | < Rhamphoryncus> | inter-unit vs intra-unit |
21:50 | < celticminstrel> | Hm; what's the difference between H and G in the WHO response? |
21:50 | < celticminstrel> | It probably doesn't matter, but I'm curious. |
--- Log closed Thu May 27 21:50:17 2010 |
--- Log opened Thu May 27 21:50:31 2010 |
21:50 | | TheWatcher [chris@Nightstar-b4529b0c.zen.co.uk] has joined #code |
21:50 | | Irssi: #code: Total of 22 nicks [5 ops, 0 halfops, 0 voices, 17 normal] |
21:50 | | mode/#code [+o TheWatcher] by Reiver |
21:51 | | Irssi: Join to #code was synced in 53 secs |
21:52 | <@ToxicFrog> | celticminstrel: G is set away. H is not. |
21:52 | < celticminstrel> | Well, that could be useful. |
21:53 | | * ToxicFrog snrks at this commit message |
21:53 | < celticminstrel> | Ah! Gone and Here, I'm guessing. |
21:53 | <@ToxicFrog> | "Unit test: build and run, observe HM commands are absent" |
21:53 | <@ToxicFrog> | "QA test: ditto" |
21:53 | <@ToxicFrog> | "Regression risk: the very concept implies a level of effectiveness and stability never achieved" |
21:55 | < Namegduf> | XD |
21:55 | <@McMartin> | HM? |
21:56 | <@ToxicFrog> | Hardware Monitor |
21:58 | | Derakon[AFK] is now known as Derakon |
22:10 | | Zed [Zed@Nightstar-e4835f03.or.comcast.net] has joined #code |
22:53 | | Reivles [orthianz@Nightstar-41c10dd9.xnet.co.nz] has quit [Ping timeout: 121 seconds] |
23:12 | | AbuDhabi [annodomini@Nightstar-9440674e.adsl.tpnet.pl] has quit [[NS] Quit: DEATH.] |
23:49 | | Attilla [Attilla@Nightstar-27696e15.threembb.co.uk] has quit [Ping timeout: 121 seconds] |
23:54 | | You're now known as TheWatcher[T-2] |
23:56 | | You're now known as TheWatcher[zZzZ] |
--- Log closed Fri May 28 00:00:16 2010 |