--- Log opened Thu Jan 25 00:00:44 2018 20180125 00:36:55-!- irker483 [~irker@uruz.ai0867.net] has quit [Quit: transmission timeout] 20180125 00:49:49-!- celticminstrel [~celmin@unaffiliated/celticminstrel] has joined #wesnoth-dev 20180125 01:34:45-!- ToBeCloud [uid51591@wikimedia/ToBeFree] has quit [Quit: Connection closed for inactivity] 20180125 02:23:40-!- celticminstrel [~celmin@unaffiliated/celticminstrel] has quit [Ping timeout: 240 seconds] 20180125 02:32:44-!- celticminstrel [~celmin@unaffiliated/celticminstrel] has joined #wesnoth-dev 20180125 03:18:06-!- stikonas [~gentoo@wesnoth/translator/stikonas] has quit [Quit: Konversation terminated!] 20180125 03:22:59< vultraz> celticminstrel: can you make an assignment operator that takes two arguments? 20180125 03:29:47< celticminstrel> No. 20180125 03:30:40< vultraz> k 20180125 03:30:46< vultraz> helper it is 20180125 03:37:27-!- janebot [~Gambot@unaffiliated/gambit/bot/gambot] has quit [Remote host closed the connection] 20180125 03:37:33-!- janebot [~Gambot@unaffiliated/gambit/bot/gambot] has joined #wesnoth-dev 20180125 03:41:53 * DeFender1031 wonders how that would even look... 20180125 03:57:36< TadCarlucci> `i = 1, 2;' --> And we can all laugh when he asks why i is 2 and what happened to 1. 20180125 04:05:55-!- JyrkiVesterinen [~JyrkiVest@85-23-197-3.bb.dnainternet.fi] has joined #wesnoth-dev 20180125 04:14:28< JyrkiVesterinen> Well, in Lua you can do stuff like "i, j = 1, 2" 20180125 04:24:10< DeFender1031> sure, but you can't assign two different values to a single variable. 20180125 04:25:19< DeFender1031> I COULD actually see "i = (1, 2)" (with mandatory parens) as being viable for such a syntax, but why bother? At that point, you've defeated the purpose of an assignment overload and a method would be cleaner anyway 20180125 04:25:35< JyrkiVesterinen> A mismatch in the number of variables isn't a syntax error though. Lua will ignore extra expressions on the right, and if there are more in the left side, then it will assign nil. 20180125 04:26:10< JyrkiVesterinen> i = 1, 2 => i = 1, the 2 is ignored 20180125 04:26:18< JyrkiVesterinen> i, j = 1 => i = 1, j = nil 20180125 04:31:58< DeFender1031> of course. 20180125 04:32:33< DeFender1031> I actually hate that syntax and find that it makes things harder to read than assigning one at a time, but whatever, that's a matter of opinion. 20180125 04:33:16< JyrkiVesterinen> It's most useful for functions which return multiple values. 20180125 04:34:06< JyrkiVesterinen> Personally, Lua is one of my favorite languages. I enjoyed writing Lua code for Angry Birds games. :) 20180125 04:34:57< DeFender1031> It has some useful features that no other languages have 20180125 04:35:11< DeFender1031> For example, soft typing with nearly no type fudging. 20180125 04:35:27< DeFender1031> For example, table keys that accept any type and don't fudge types there either. 20180125 04:36:26< DeFender1031> it's the only language I know where "blah = {}; blah[0] = something; blah['0'] = something;" results in two separate keys rather than just one. 20180125 04:36:50< DeFender1031> It didn't NEED the somewhat newish Map() introduced into JS, since you can already use objects as keys. 20180125 04:37:23< DeFender1031> On the other hand, it has a lot of ugliness, rules that don't really make sense entirely, and ways to write nasty code that a lot of people abuse. 20180125 04:37:55< JyrkiVesterinen> A determined Real Programmer can write Fortran in any language. 20180125 04:38:22< JyrkiVesterinen> I don't count ability to write nasty code as a negative thing. 20180125 04:39:15< DeFender1031> fair. 20180125 04:40:20< DeFender1031> but for example, building a table with function returns that return multiple values will put the multiple values in the table ONLY for the last call. 20180125 04:40:29< DeFender1031> rather than for all or for none 20180125 04:40:40< DeFender1031> that seems inconsistent to me 20180125 04:42:57< DeFender1031> I vaguely recall that I noticed a couple of other things like it seemed the language should have been able to do but wasn't from when I was working with lua on my curently comatose campaign. 20180125 04:43:33< JyrkiVesterinen> I don't understand what you mean with your example. 20180125 04:43:44< JyrkiVesterinen> my_table = {func()} 20180125 04:44:10< DeFender1031> no, my_table = {func1(), func2(), func3()} 20180125 04:44:10< JyrkiVesterinen> IIRC, that does put all return values into the table, no matter how many times you do it. 20180125 04:44:36< JyrkiVesterinen> Oh, I see. 20180125 04:44:49< DeFender1031> I seem to recall that it would take the first value from func1, the first value from func2, and all values from func3. 20180125 04:45:14< JyrkiVesterinen> That's because of the rule that if you call multiple functions in the same line, extra return values from all but the last one are ignored. 20180125 04:45:56< JyrkiVesterinen> Yes, I agree that it's inconsistent, and it would be slightly better if the Lua interpreter ignored extra return values from *all* functions in this case. 20180125 04:46:07< DeFender1031> you want to offer multi-value return, fine, but make it work consistently. Either your multi-value return fully expands into a multi-value assignment or it doesn't. This "all but the last" rule is an idiotic halfway point 20180125 04:46:40< JyrkiVesterinen> I think they wanted to optimize it for productivity without making it completely unreadable. 20180125 04:47:22< DeFender1031> perhaps, but I'm arguing that halfway productive and halfway readable means neither of the two, and the worst of both worlds 20180125 04:48:03< DeFender1031> JS's new ... syntax for what is essentailly multi-value stuff is the best of both, and with three little dots, clearly states whether you want expansion or not. 20180125 04:48:16< JyrkiVesterinen> If you do "outer_function(func1(), func2(), func3())", you know exactly that the return value of func2 will be the second parameter and the return value of func3 will be the third parameter, no matter how many values func1 and func2 return. 20180125 04:48:32< DeFender1031> sure. 20180125 04:48:50< JyrkiVesterinen> At the same time, the interpreter doesn't "needlessly" throw away extra return values from func3. It might be good especially if outer_function is variadic. 20180125 04:49:06< DeFender1031> and especially if you have callbacks such that you don't know how many each one will return and throw everything off, that makes some amount of sense 20180125 04:49:28< DeFender1031> but once you realize that, you realize that multi-return undifferentiated by syntax becomes problematic. 20180125 04:50:22< JyrkiVesterinen> I don't recall running into such problems when I worked with Lua professionally for 1,5 years. 20180125 04:50:43< DeFender1031> which is why I like having an explicit syntax for spread syntax. 20180125 04:50:59< JyrkiVesterinen> The rules are still intuitive and easy to remember, even if they aren't fully consistent. 20180125 04:51:38< DeFender1031> I find that the more used to a language someone is, the harder it is for them to step outside of it and look objectively at the good and bad things about it. 20180125 04:51:45< JyrkiVesterinen> Even with Lua's very easy multi-return, the vast majority of functions still return only zero or one values. 20180125 04:51:49< DeFender1031> I'm guilty of this too. 20180125 04:52:24< DeFender1031> right. which is why I'm saying that for the rare cases where it makes sense to return more, you lose very little by requiring an explicit spread syntax. 20180125 04:52:40< DeFender1031> and gain a lot of clarity 20180125 04:52:46< JyrkiVesterinen> Yeah, that's fair. 20180125 04:53:52< DeFender1031> you want to use a single value? "call()". you want to use ALL the values? "...call()". You want to use a specific value other than the first? "{...call()}[2]". Etc. 20180125 04:54:56< DeFender1031> (JS's spread syntax works a little differently than that, where it actually expects functions to return an array and spread THAT, but what I just said probably works better for lua's existing structure... not that it'll happen, since lua already does spread automatically in the cases where it does it.) 20180125 04:55:01< JyrkiVesterinen> JavaScript's way to concatenate arrays is beautiful. arr.push(...arr2); 20180125 04:55:15< JyrkiVesterinen> (Doesn't work if arr2 is very large (hundreds of values).) 20180125 04:55:21< DeFender1031> or arr.concat(arr2); 20180125 04:55:39< DeFender1031> which has existed far longer than the ... method. 20180125 04:55:39< JyrkiVesterinen> Concat isn't in-place. It constructs a new array. 20180125 04:55:46< DeFender1031> hmm 20180125 04:55:56< DeFender1031> arr = arr.concat() 20180125 04:56:18< JyrkiVesterinen> Yeah, that works, but it's less efficient for small arrays. 20180125 04:56:25< DeFender1031> and yeah, there's not a lot of pattern to which functions operate in place and which don't 20180125 04:57:40< DeFender1031> when I write my own classes, I usually provide both in-place and as-a-copy versions of methods. 20180125 04:58:10< DeFender1031> unless of course it's a simple enough class that I want the data to be immutable, in which case it's only as-copy 20180125 04:58:34< DeFender1031> but i'll never have just one version of each method and some return a copy and some operate in place. 20180125 04:59:18< DeFender1031> well, aside from a "whatever.copy()" method, for which, naturally, the in-place version is just "whatever" 20180125 05:00:06< JyrkiVesterinen> Just what kind of classes are you writing? For nearly all game data, it doesn't make sense to keep around extra copies and you want to modify the object in-place. 20180125 05:00:24< JyrkiVesterinen> As-a-copy methods usually only make sense for low-level objects such as arrays and strings. 20180125 05:00:26< DeFender1031> i'm not talking games at this point 20180125 05:00:34< DeFender1031> i'm talking low-level things 20180125 05:00:50< DeFender1031> a DateTime class for instance. 20180125 05:01:03< DeFender1031> or an enhanced string class 20180125 05:01:09< JyrkiVesterinen> Hmm, I see. 20180125 05:01:13< DeFender1031> things like that. 20180125 05:01:34< DeFender1031> yeah, for high-level calsses, I tend to have ONLY in-place stuff 20180125 05:02:17< JyrkiVesterinen> The Angry Birds codebase was already mature by the time I joined, and therefore I didn't need to write classes like that. (And even if I had a need for one, initially I'd have only implemented the functionality I needed immediately.) 20180125 05:02:29< DeFender1031> my point was more that I will either have all methods act on copies, all methods act in-place, or have two versions of every method with a common suffix for differentiating one from the other, but I won't have one version of each function where some do in-place and others do copy. 20180125 05:03:44< JyrkiVesterinen> Indeed, it obviously shouldn't be confusing whether a function modifies the object in-place or creates a new copy. 20180125 05:04:27< DeFender1031> so usually if i have both kinds, "name" will be in-place and "nameCopy()" will be the copy version 20180125 05:04:56< JyrkiVesterinen> BTW, Ruby has one solution to that. A common practice in Ruby code is that any method that modifies the object in-place (for a class that also has copying methods) has a name that ends with an exclamation mark. 20180125 05:05:15< DeFender1031> (also, usually the copy version just does "this.copy().name()" internally except in cases where there's a more efficient method than that) 20180125 05:05:40< DeFender1031> that's just a naming convention too though, no? 20180125 05:05:42< JyrkiVesterinen> For example: http://ruby-doc.org/core-2.5.0/String.html#method-i-sub-21 20180125 05:05:58< DeFender1031> I could just as easily do that in any language with an _. 20180125 05:06:00< JyrkiVesterinen> Correct, it's just a convention. The interpreter doesn't enforce it. 20180125 05:06:23< DeFender1031> so name() vs name_() 20180125 05:06:32< DeFender1031> could work just as well for in-place vs. copy. 20180125 05:06:43< JyrkiVesterinen> But it's worth noting that Ruby's standard library, as long as any library with any importance, honors that practice. 20180125 05:07:00< JyrkiVesterinen> So if your own code isn't following it, you're just asking for trouble. 20180125 05:07:17< DeFender1031> I tend to prefer full word names for things even if they're long, as they're more obviously self-documenting without needing to know of specific conventions. 20180125 05:07:45< DeFender1031> right, so if the particular language itself uses a certain convention, I might use that too. 20180125 05:07:54< DeFender1031> then again, I might not. 20180125 05:09:32< DeFender1031> but i'm more likely to use a convention other than "full words differentiating what things do" if it's familiar to a language already than if it's not. 20180125 05:10:22< DeFender1031> basically, I value consistency, readability, and intuitiveness. 20180125 05:10:23< JyrkiVesterinen> Ruby in general is a highly concise language. For example, it allows you to omit parentheses in method calls, and nearly all production Ruby code does that. 20180125 05:10:32< DeFender1031> like lua. 20180125 05:10:36< JyrkiVesterinen> Take this line for example: 20180125 05:10:37< JyrkiVesterinen> object_id = ActiveRecord::Base.connection.object_id 20180125 05:10:54< JyrkiVesterinen> "connection" is a method call. So is "object_id". 20180125 05:11:19< JyrkiVesterinen> Neither method receives any parameters, and therefore the calls can be just chained like that. 20180125 05:11:27< DeFender1031> oh 20180125 05:11:32< DeFender1031> interesting 20180125 05:11:40< DeFender1031> that's what you mean 20180125 05:11:55< DeFender1031> I thought you meant like lua's method{things} or method"things" 20180125 05:12:22< DeFender1031> so it's like defining a getter in JS, except that methods with no params can explicitly act like getters... 20180125 05:12:36< DeFender1031> interesting 20180125 05:12:59< JyrkiVesterinen> Such getters are usually created by defining an instance variable of the same name and then creating a getter for it. 20180125 05:13:07< JyrkiVesterinen> The way to create a getter is just: 20180125 05:13:14< JyrkiVesterinen> attr_reader :connection 20180125 05:13:27< JyrkiVesterinen> attr_reader itself is also a method. 20180125 05:13:41< JyrkiVesterinen> (The parameter there is a symbol, i.e. an immutable string.) 20180125 05:13:42< DeFender1031> hmm 20180125 05:13:57< celticminstrel> If only there were a language that merges the best parts of Lua and JS. >_> 20180125 05:14:44< JyrkiVesterinen> *Calling* attr_reader at the time when the class is being defined creates a getter for the instance variable of the given name (obtained with reflection) and injects the getter into the class. 20180125 05:14:46< DeFender1031> celticminstrel, meh, it still wouldn't be my ideal language. I'd want the inheritance model of C++, for instance. 20180125 05:15:34< DeFender1031> and the ability to pass by reference. 20180125 05:15:35< celticminstrel> I actually really like the JS prototype-based inheritance model, which Lua kinda has too. 20180125 05:15:44< DeFender1031> and the ability to pass OBJECT not by reference... 20180125 05:16:05< DeFender1031> i have several issues with the prototype-based model. 20180125 05:16:16< JyrkiVesterinen> I also like the way you can define classes in Lua with metatables. 20180125 05:16:17< DeFender1031> the biggest of which is lack of multiple inheritance 20180125 05:16:31< celticminstrel> Ah, yeah, that's true. 20180125 05:16:39< DeFender1031> lesser is lack of private and protected 20180125 05:17:06< celticminstrel> I don't really care about access protection TBH, but it'd be nice to have simple multi-inheritance in JS or Lua. 20180125 05:17:24 * celticminstrel says simple because it is possible in both, with a lot of work. 20180125 05:17:35< DeFender1031> (I actually recently wrote my own class creation function for JS that basically gives you those things, but is only really friendly to use if you're also using the C preprocessor and the macros it gives you to work with them) 20180125 05:17:47< JyrkiVesterinen> Nothing blocks you from implementing multiple inheritance with Lua metatables. 20180125 05:17:54< JyrkiVesterinen> You can even create a function for that. 20180125 05:18:05< DeFender1031> JyrkiVesterinen, true, but I find lua metatables to be rather clunky. 20180125 05:18:37< celticminstrel> IIRC I found JS's prototype system to be easier to understand than Lua metatables. On the other hand, last I checked, JS doesn't allow you to overload operators. 20180125 05:19:00< JyrkiVesterinen> I like how powerful metatables are. Most of the time, you can just deal with metatables in functions (such as a function that defins a class) and forget that they exist when you write day-to-day code. 20180125 05:19:20< DeFender1031> yeah, operator overloads would be nice. 20180125 05:19:49< DeFender1031> also, garbage collection and only garbage collection for memory management can be a bitch 20180125 05:20:07< DeFender1031> sure, in 98% of cases, reference counting and GC is fine. 20180125 05:20:14< JyrkiVesterinen> That's what you get with nearly every scripting language under the sun. 20180125 05:20:31< celticminstrel> JS functions are also objects and you can add attributes to them. 20180125 05:20:40< DeFender1031> but unlike C++ which gives you tools to do those automatically in the cases where it makes sense, and manually if you need more control, JS and Lua don't have that option. 20180125 05:20:43< celticminstrel> (That's true in Python too IIRC) 20180125 05:20:54< DeFender1031> right 20180125 05:21:16< DeFender1031> But if we're talking ideal language, it's something I'd want also. 20180125 05:21:17< JyrkiVesterinen> C++ does not have garbage collection, you know. 20180125 05:21:31< JyrkiVesterinen> It offers reference couting, but that approach has its own problems. 20180125 05:21:47< DeFender1031> JyrkiVesterinen, sure it does. It has all sorts of managed pointer classes, and IIRC the newest proposed spec has GC as well. 20180125 05:22:32< JyrkiVesterinen> Such as that you can create ownership cycles (especially if you capture shared_ptrs in lambdas). 20180125 05:22:58< JyrkiVesterinen> Reference counting is not full garbage collection. 20180125 05:23:00< DeFender1031> And yes, celticminstrel, functions as objects is nice, but some way of creating a constructor that returns a function WITH a prototype without having to manually set __proto__ which is slow would be nice. 20180125 05:23:45< celticminstrel> You mean Object.create or whatever, right? 20180125 05:23:50< DeFender1031> (which would be trivial if it supported operator overloads) 20180125 05:24:05< celticminstrel> Though it was possible even before that, I think. 20180125 05:24:06< DeFender1031> no, I mean new SomeConstructorFunctionThing(). 20180125 05:24:19< DeFender1031> though Object.create too 20180125 05:24:31< DeFender1031> since that's basically the same, but without a constructor. 20180125 05:24:40< celticminstrel> Oh yeah, true. 20180125 05:26:36< DeFender1031> "blah = new Constructor(some, args);" IIRC is equivalent to "blah = Object.create(Constructor.prototype); temp = Constructor.call(blah, some, args); if(temp instanceof Object) { blah = temp; }" 20180125 05:27:32< DeFender1031> so yeah, either way, would be nice to end up with blah being both a function and an instance of Constructor. 20180125 05:27:54< DeFender1031> (again, without setting __proto__ on a newly-created function each time, which is slow) 20180125 05:28:05< celticminstrel> Hm. 20180125 05:28:19< DeFender1031> The framework I mentioned above that I recently wrote actually does that for lack of a better way, but I'm not so happy about it 20180125 05:28:26< celticminstrel> But doesn't __proto__ for a function need to be Function.prototype? 20180125 05:28:45< celticminstrel> Or at least the prototype chain needs to include it... 20180125 05:28:52< celticminstrel> Which I guess is nowhere near the same thing. 20180125 05:28:57< DeFender1031> need to be? no, not strictly, though it's a good idea to have it in the prototype chain somewhere. 20180125 05:29:25< DeFender1031> If, for example, Constructor.prototype was created from Function's prototype, that'd work. 20180125 05:29:42< DeFender1031> (Which I ensure to do as well.) 20180125 05:31:31< DeFender1031> Basically, someFunc.__proto__ will be function.prototype by default, but if instead someFunc.__proto__.__proto__.__proto__.(however many) is Function.prototype, that'll also behave as normal. Also, IINM, it can still be something else, it just means that you can't call things like ".call" or ".bind" on it. 20180125 05:31:44< DeFender1031> But I believe it itself is still callable. 20180125 05:31:56< DeFender1031> Could be wrong though, was never stupid enough to try it. 20180125 05:32:49< DeFender1031> Also, even without the prototype, you can always do Function.prototype.bind.call(functionWithoutFunctionProto) 20180125 05:33:51< DeFender1031> (I actually think I DO have a couple of places in my code where I have some wacky "Function.prototype.apply.bind.call" type stuff...) 20180125 05:34:26< DeFender1031> But as I've said here many times, I'm a crazy person and I tend to try to do things with languages that they weren't designed for. 20180125 05:35:18< celticminstrel> So on another topic, did you still plan to do that Wesnoth string parsing functions rewrite or update or something? 20180125 05:35:25< DeFender1031> yeah, I have this line in my code: bind = Function.prototype.bind.call.bind(Function.prototype.bind) 20180125 05:35:35< celticminstrel> Heh. 20180125 05:35:49< celticminstrel> ISTR using a bind.call at least once. 20180125 05:37:12< DeFender1031> Which is just a fancy way of returning a function that binds the function passed as the first parameter to the object passed as the second, with the remaining parameters. Essentially bind(someFunc, obj, params, ...) is equivalent to someFunc.bind(obj, params, ...) 20180125 05:37:43< celticminstrel> ISTR bound functions in JS could not be further bound... 20180125 05:38:51< DeFender1031> Ah, yes. My plans to work on wesnoth are unfortunately on hold for the time being. I had really wanted to, but sadly, I got a promotion, a raise, and far more work than I wish I had. Hopefully things will lighten up in not too long, but no promises. 20180125 05:39:15< DeFender1031> you are correct, bound functions can't be further bound 20180125 05:39:26< DeFender1031> or rather, .bind() on them is simply ignored. 20180125 05:39:36< DeFender1031> (I think it returns a new function object though.) 20180125 05:39:45< DeFender1031> But that's not what's going on here. 20180125 05:40:10< DeFender1031> btw, just so it doesn't get los, vultraz, see a few lines up about my plans to work on wesnoth. 20180125 05:40:14< DeFender1031> lost* 20180125 05:40:30< celticminstrel> ...wait, isn't Function.prototype.bind.call the same as just Function.prototype.call? 20180125 05:40:34< DeFender1031> no. 20180125 05:40:43< DeFender1031> that .bind isn't being called. 20180125 05:40:48< DeFender1031> I'm doing .call ON .bind. 20180125 05:40:58< DeFender1031> no 20180125 05:41:02< celticminstrel> That would be .bind.call(...) 20180125 05:41:08< celticminstrel> Not .bind.call.bind(...) 20180125 05:41:10< DeFender1031> i'm doing a bind ON the .call OF .bind 20180125 05:41:54< DeFender1031> essentially, all it's doing is making a bind() function which can be called on nothing, and uses "operative object as first parameter" style passing, rather than "operative object as this" style passing. 20180125 05:42:11< celticminstrel> I'm just saying that I think the first bind in there is redundant. 20180125 05:42:29< DeFender1031> as I said, with that line, "bind(someFunc, obj, params, ...) is equivalent to someFunc.bind(obj, params, ...)" 20180125 05:42:34< DeFender1031> no, it's not. 20180125 05:43:10< celticminstrel> You sure? 20180125 05:43:19< DeFender1031> yes. 20180125 05:43:32< DeFender1031> wait... hmm 20180125 05:44:14< DeFender1031> now you've confused me. 20180125 05:44:29< DeFender1031> I thought I knew what I was doing... 20180125 05:44:32< DeFender1031> :P 20180125 05:44:34< celticminstrel> :P 20180125 05:44:47< DeFender1031> ah, yes, okay, I seem 20180125 05:44:52< DeFender1031> no, it's not redundant. 20180125 05:45:30-!- travis-ci [~travis-ci@ec2-54-197-145-119.compute-1.amazonaws.com] has joined #wesnoth-dev 20180125 05:45:31< travis-ci> wesnoth/wesnoth#16204 (master - 207e763 : Charles Dang): The build has errored. 20180125 05:45:31< travis-ci> Build details : https://travis-ci.org/wesnoth/wesnoth/builds/332778242 20180125 05:45:31-!- travis-ci [~travis-ci@ec2-54-197-145-119.compute-1.amazonaws.com] has left #wesnoth-dev [] 20180125 05:45:50< DeFender1031> oh! 20180125 05:46:01< DeFender1031> okay, you're actually right, sort of. 20180125 05:46:04< celticminstrel> Function.prototype.bind.call.bind(...) 20180125 05:46:33< celticminstrel> Function.prototype.bind is the bind function. The bind function does not have a member named "call", but its prototype, Function.prototype, does, so... 20180125 05:46:48< DeFender1031> you're saying that since Function.prototype.bind.call and Function.prototype.call SHOULD be the exact same function, I don't need that first one. 20180125 05:46:50< celticminstrel> Function.prototype.bind.call == Function.prototype.call 20180125 05:46:54< celticminstrel> Yeah. 20180125 05:46:56< DeFender1031> right right. 20180125 05:47:09< DeFender1031> yeah, okay, you seem to have figured out what i'm doing here better than I did :P 20180125 05:47:42< celticminstrel> <_< 20180125 05:47:56< DeFender1031> so yes, in theory, that's true. In practice, I tend to use the actual source I'm binding for... umm... erm... cla...ri...ty.... >_> *whistles innocently* 20180125 05:48:29 * DeFender1031 realizes how stupid that sounds given the amount of confusion in the previous bit of conversation 20180125 05:50:16< DeFender1031> however, take a simpler case. I tend to prefer "getThingPos = someArray.indexOf.bind(someArray)" to "getThingPos = Array.prototype.indexOf.bind(someArray)" even though they're equivalent. 20180125 05:50:42< DeFender1031> the reason not being that the former is shorter, but because it makes it clear that I'm binding the things own method to the thing. 20180125 05:51:19< DeFender1031> Also, in more complex cases, some subclass may have overloaded the prototype's version with its own, or even the object itself may have rewritten the method to enhance it. 20180125 05:51:54< DeFender1031> Obviously, if someone's been screwing with .bind and .call's methods, they're asking for trouble, but still, like I said, I prefer to use the object being bound as the method source. 20180125 05:52:25< DeFender1031> So yes, while you're technically correct that I don't need that first .bind in there at all, the method source is .bind, and therefore I prefer it in. 20180125 05:52:47 * DeFender1031 wonders if he should stop digging while he's behind... 20180125 05:53:12< celticminstrel> I think I actually see what you mean. 20180125 05:54:01< celticminstrel> It's like native_bind = Function.prototype.bind; native_bind.call.bind(native_bind). 20180125 05:54:36< celticminstrel> ^ ; bind = 20180125 05:55:13< DeFender1031> Right. Exactly. I prefer "X.method.bind(X)" to "someOtherAccessPointForThatMethodOfX.bind(X)". It just so happens that X in this case is "Function.prototype.bind". 20180125 05:57:48< DeFender1031> Occasionally, of course, I bind something that ISN'T a method of X, but that's different. 20180125 05:57:48< DeFender1031> Oh yeah. That's another thing I'd prefer different in my ideal language. Saner handling of the "this" keyword. 20180125 05:57:48< DeFender1031> Instead of requiring binds all over the place. 20180125 05:57:50< DeFender1031> One way I think JS would have been vastly improved is if instead of "this" being "window" when a function is called straight, "this" were to instead be whatever "this" was in the parent closure where the function was defined. 20180125 05:57:58< JyrkiVesterinen> Doesn't ES6 improve the situation with arrow functions? 20180125 05:58:18< celticminstrel> They keep adding more and more stuff to JS... 20180125 05:58:22< DeFender1031> kind of, but arrow functions are limited in what you can sanely put into them. 20180125 05:58:34< DeFender1031> they do keep adding more stuff 20180125 05:58:35< celticminstrel> Some of it pointless, like the class keyword. 20180125 05:58:41< DeFender1031> heh. 20180125 05:59:14< DeFender1031> yeah, a lot of it is just fancier at best, and usually just uglier, ways of doing things you can already do just fine. 20180125 05:59:16< JyrkiVesterinen> I like it feature-rich languages. Add all the stuff you want! 20180125 05:59:18< celticminstrel> Which IIUC is just syntactic sugar for something that was already possible and not even particularly difficult. 20180125 05:59:33< celticminstrel> JyrkiVesterinen: Well, as long as it doesn't turn into a mess like PHP. 20180125 05:59:42< DeFender1031> For example, arrow function syntax looks butt ugly to me, and if it weren't for the fact that it auto-bound this, i'd call it completely useless. 20180125 06:00:05< celticminstrel> Does "arrow function" mean traditional math notation for a mapping? 20180125 06:00:10< DeFender1031> no. 20180125 06:00:20< celticminstrel> Something like (parameters) -> expression 20180125 06:00:29< DeFender1031> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions 20180125 06:00:47< JyrkiVesterinen> PHP has multiple problems, including complete disregard for consistency early on, and way too strong focus on backwards compatibility (which is why theyäre keeping around that ISO 8601 that isn't, for example). 20180125 06:01:05< celticminstrel> So that's a yes then, except with => instead of -> 20180125 06:01:08< DeFender1031> oh, so then yes. 20180125 06:01:14< DeFender1031> hmm 20180125 06:01:20< DeFender1031> didn't realize that was a math thing. 20180125 06:01:30< DeFender1031> okay. still ugly to me in the middle of code, but whatever. 20180125 06:01:43< JyrkiVesterinen> http://i.imgur.com/ASxdrrF.png 20180125 06:01:47< aeth> how does that make code clearer 20180125 06:01:53< celticminstrel> Math uses some particular fancy arrow IIRC. 20180125 06:02:00< DeFender1031> JyrkiVesterinen, i LOVE complaining about PHP! 20180125 06:02:00< celticminstrel> Possibly the one that looks like |--> 20180125 06:02:24< JyrkiVesterinen> DeFender1031: Have you seen https://www.reddit.com/r/lolphp/top/?sort=top&t=all ? 20180125 06:02:30< celticminstrel> . . . 20180125 06:02:32< JyrkiVesterinen> There are a lot of gems there. :D 20180125 06:02:33< DeFender1031> JyrkiVesterinen, I discovered just today that despite php offering signal handling, it doesn't actually work the way traditional C/POSIX signals do. 20180125 06:02:42< celticminstrel> ANYWAY bedtime. >_> 20180125 06:02:55< DeFender1031> JyrkiVesterinen, and http://phpsadness.com/ 20180125 06:03:02< DeFender1031> And I keep my own list that's on neither. 20180125 06:04:44-!- celticminstrel [~celmin@unaffiliated/celticminstrel] has quit [Quit: And lo! The computer falls into a deep sleep, to awake again some other day!] 20180125 06:08:28< DeFender1031> JyrkiVesterinen, My boss and I once spent 5 hours tracking down an insidious bug where we had a loop where on a series of entries failing for legitimate reasons, for some reason, every OTHER iteration of was failing with a busy resource that should in no way have been busy. It turned out that because there was a try and catch going on and the exceptions contained a backtrace including object handles, some RAII destructors 20180125 06:08:29< DeFender1031> weren't being called by the throw, so that the catch still held onto them, and since PHP only has function scope, the exception caught there STILL existed even once the catch was completed, the resource remained busy until the next iteration threw an error that it was busy, at which point the exception in the catch was overwritten with the new one and the destructor called, freeing up the old one. 20180125 06:09:04< DeFender1031> The point of the story though is that because PHP keeps active handles in a backtrace, destructors aren't called when you expect them to be called. 20180125 06:09:30< JyrkiVesterinen> That's not really PHP specific. 20180125 06:09:52< JyrkiVesterinen> Developers are generally advised not to rely on Java finalizers or C# destructors either. 20180125 06:10:15< DeFender1031> Oh, another fun one: foreach($something as &$element) { doStuff(); } foreach($somethingElse as $element) { doOtherStuff(); } will lead to the last element in $something being overwritten with the last element in $somethingElse. 20180125 06:10:58< DeFender1031> Perhaps, but RAII is an important pattern, and if you're coming from a language that DOESN'T mix data and code, you don't know that this is a problem. 20180125 06:11:28< JyrkiVesterinen> That overwriting problem is just insane. >_< 20180125 06:11:50< JyrkiVesterinen> RAII is pretty much C++ exclusive. No other notable language has it. 20180125 06:11:52< DeFender1031> JyrkiVesterinen, but once you know about it, it's obvious why it happens. 20180125 06:12:27< DeFender1031> well, RAII mostly works in php, so long as you're aware of the gotchas. 20180125 06:12:57< DeFender1031> So now, we make sure in any catch to unset the exception object as soon as we've done everything we intend to do with it. 20180125 06:13:09< JyrkiVesterinen> As I said, the generic advice I have got is not to attempt to rely on RAII in any language other than C++. 20180125 06:14:07< DeFender1031> But no sane program should be picking through its own backtrace to find out where it went wrong. If it could do that, it should have handled whatever it was on the way up. The ONLY reason for a backtrace is for reporting, which means that it shouldn't contain ACTIVE code object, but merely some representation of them. 20180125 06:14:38< DeFender1031> Meh. We use it where we can. 20180125 06:15:04< JyrkiVesterinen> I think the power to access the backtrace programmatically is nice, even if there isn't much use for it. 20180125 06:16:43< DeFender1031> I think it's mixing data and code, which is never a good thing 20180125 06:17:00< DeFender1031> And, as I mentioned, it means that destructors don't fire when you think they do. 20180125 06:17:16< DeFender1031> Even if not RAII, just anything you're doing with a destructor can get messed up. 20180125 06:17:30< JyrkiVesterinen> Destructors are quite unreliable in garbage-collected languages anyway. 20180125 06:17:45< DeFender1031> only if you have circular references. 20180125 06:17:54< DeFender1031> if not, they're entirely predictable. 20180125 06:18:01< DeFender1031> but yes, that's another issue with GC 20180125 06:18:09< DeFender1031> and why I dislike GC languages. 20180125 06:18:13< JyrkiVesterinen> Circular references are very easy to get in a GC'd language. 20180125 06:18:20< DeFender1031> certainly 20180125 06:18:46< DeFender1031> in cases where we rely on destructors in PHP, we go to great lengths to avoid them, though. 20180125 06:19:06< JyrkiVesterinen> Because the GC frees you from having to think about object ownerships, you can just pass references to objects all over the place and trust that the GC will get rid of everything you don't need. 20180125 06:19:06< DeFender1031> Heck, we go to great lengths to avoid them in JS too, since they can cause slowdowns. 20180125 06:19:27< DeFender1031> Sure, but at the cost of knowing what your code is actually doing when. 20180125 06:20:05< JyrkiVesterinen> And then you'll soon create a cycle somewhere and not even notice it. (After all, the only immediately visible cost is a couple dozen bytes higher memory usage, completely lost in the noise.) 20180125 06:21:04< DeFender1031> And random interrupts as the GC kicks in at inconvenient times and causes input lag... 20180125 06:21:14< JyrkiVesterinen> In the game project I'm about to start developing at work, I don't plan to rely on destructors on anything. 20180125 06:21:19< JyrkiVesterinen> (Unity3D, C#.) 20180125 06:22:12< DeFender1031> and that's a valid choice, for sure. 20180125 06:23:11< DeFender1031> I just tend to think that they solve a lot of problems in terms of automatic cleanup 20180125 06:23:43< JyrkiVesterinen> Sure, when they work reliably. 20180125 06:24:06< JyrkiVesterinen> And the POV I take is that they don't work reliably in GC'd languages and shouldn't be used in them. 20180125 06:24:22< DeFender1031> like, with proper destructors, you can usually write enough code to do ALL the automatic cleanup you need. With GC, you automatically get 98% of the automatic cleanup you need, but the remaining 2% builds up quickly and is a nightmare. 20180125 06:24:41< JyrkiVesterinen> That I have to agree with. 20180125 06:24:45< DeFender1031> that's fair. 20180125 06:25:23< JyrkiVesterinen> Another open source project I develop in my spare time is a music visualizer for Windows, written in C#: https://sourceforge.net/projects/keppi/ 20180125 06:25:30< DeFender1031> example, in JS, cleaning up event handlers, timeout handlers, or interval handlers which pointing to useless data that nothing else uses is a pain in the butt. 20180125 06:25:49< JyrkiVesterinen> I use Windows Media Foundation for audio decoding, through a wrapper called SharpDX. 20180125 06:26:18< JyrkiVesterinen> WMF objects aren't managed, and therefore I have the responsibility to free them when I no longer need them. 20180125 06:26:42< JyrkiVesterinen> And therefore I have needed to write all the code to free them manually. 20180125 06:26:50< JyrkiVesterinen> The codebase doesn't have a single destructor. 20180125 06:27:39< JyrkiVesterinen> And, frankly, keeping track of them is a pain. I wish I had C++'s reliable destructors in my disposal. 20180125 06:28:40< DeFender1031> without destructors, you basically have to wrap any context that needs to do cleanup and calls other stuff that can throw in a try and catch which does the clean up and rethrows also (or a finally for the cleanup if finally exists in the language you're using) 20180125 06:29:15< JyrkiVesterinen> Nearly all GC'd languages have finally. 20180125 06:29:35< JyrkiVesterinen> C++ doesn't have finally simply because it doesn't need it. RAII is an alternative to finally. 20180125 06:29:41< DeFender1031> true that. 20180125 06:31:28< DeFender1031> but either way, point is, anything that creates a resource that needs cleaning up needs to do: resource = createResource(); if(isValid(resource)) { try { moreStuff(); } catch(whatever) { throw(whatever); } finally { cleanUp(resource); } } else { handleResourceAcquisitionError(); } 20180125 06:31:52< DeFender1031> and if you have a context that sets up 5 such resources, you're going to have to nest all that crap 5 times. 20180125 06:33:25< DeFender1031> with RAII, you only need the validity checks, and everything else can be handled automatically by the destructor based on whether they were actually initialized or not. 20180125 06:33:42< JyrkiVesterinen> Actually, it gets worse if objects have longer lifetimes. 20180125 06:33:44< DeFender1031> anyway, yeah, that's why I prefer RAII to GC. 20180125 06:33:53< DeFender1031> what do you mean? 20180125 06:34:44< JyrkiVesterinen> In C#, the common pratice is that any object that owns unmanaged resources needs to implement IDisposable, and Dispose() must be called when you're done with that object. 20180125 06:35:05< JyrkiVesterinen> Using statement can do that for you if the object is only in the stack. 20180125 06:35:24< DeFender1031> right. and I do something similar in JS for objects that own event handler callbacks or timers or whatnot to tear them apart. 20180125 06:35:33< DeFender1031> But it means a lot more manual management of stuff. 20180125 06:35:49< JyrkiVesterinen> But if such an object is owned by another object, then the *parent* class also needs to implement IDisposable and dispose the object in its Dispose() method. 20180125 06:36:22< JyrkiVesterinen> Even worse if the ownership of something can be transferred between multiple classes. 20180125 06:36:23< DeFender1031> Basically, I find that the argument made in favor of GC is "it manages things for you automatically" except that the amount of things which could otherwise be managed automatically that are now not outweighs the amount of stuff that it DOES manage automaticlaly. 20180125 06:36:48< JyrkiVesterinen> This is the worst case of such an ownership transfer in the keppi codebase: https://sourceforge.net/p/keppi/code/HEAD/tree/tags/3.60/VisualizationWindow.xaml.cs#l332 20180125 06:37:18< DeFender1031> yeah, ownership transfer can be painful too. 20180125 06:37:18< JyrkiVesterinen> And yes, I agree. RAII is superior. 20180125 06:37:43< JyrkiVesterinen> The only thing I have been saying is that it isn't PHP's fault. 20180125 06:37:57< DeFender1031> fair enough. 20180125 06:37:58< JyrkiVesterinen> C++ is pretty much the only notable reference-counting language we have. 20180125 06:41:52-!- JyrkiVesterinen [~JyrkiVest@85-23-197-3.bb.dnainternet.fi] has quit [Quit: .] 20180125 06:41:56< DeFender1031> truth is, we don't work with many GC languages if we can avoid it. We use C++ for anything we can, but there's just be too much we'd need to reinvent because it's not offerred to make a webserver that served pages from C++, so we're stuck with PHP for that, and of course for clientside, you're basically stuck with either JS or one of its transpilable children. 20180125 06:42:06< DeFender1031> oh... you're gone. 20180125 06:42:38< DeFender1031> well, that was a fun conversation anyway. 20180125 07:15:32-!- irker051 [~irker@uruz.ai0867.net] has joined #wesnoth-dev 20180125 07:15:32< irker051> wesnoth: Charles Dang wesnoth:master d98093ebbac8 / src/ (config_attribute_value.cpp config_attribute_value.hpp): Config Attribute Value: added write_if_not_empty helper https://github.com/wesnoth/wesnoth/commit/d98093ebbac88e7bec471e4831a0a4729052fd83 20180125 07:15:35< irker051> wesnoth: Charles Dang wesnoth:master 438e021a27d0 / src/ (editor/map/map_context.cpp time_of_day.cpp): Editor: exclude some rarely-used keys from [time] and [item] if empty https://github.com/wesnoth/wesnoth/commit/438e021a27d02575d236800cb346f355a61c3fa5 20180125 07:29:24-!- JyrkiVesterinen [~JyrkiVest@195-192-251-124.s1networks.fi] has joined #wesnoth-dev 20180125 07:29:34< JyrkiVesterinen> DeFender1031: have you heard of http://www.tntnet.org/ ? 20180125 07:30:08< JyrkiVesterinen> And on client-side, compiling C++ to asm.js and WebAssembly with Emscripten would be one option. 20180125 07:30:47< JyrkiVesterinen> Also, even if you don't use C++ for server-side, there are still much better options than PHP. 20180125 07:31:29< JyrkiVesterinen> My employer is using JavaScript server-side, via Node.js. (The game I'll soon start developing will have a Node server as well, and I'm the lead developer for both client and server parts.) 20180125 07:33:07< DeFender1031> i hadn't, but put a different way, none of the things you're suggesting existed when we first created out product and now we're in too deep to switch over. 20180125 07:34:05< JyrkiVesterinen> I see. Rewriting definitely isn't a good option when you have a huge existing codebase. 20180125 07:34:46< DeFender1031> we'regoing on close to a decade by now 20180125 07:37:46< DeFender1031> so what I said was true at the time anyway 20180125 07:38:02< DeFender1031> this tntnet thing looks interesting though. I'll keep it in mind for any new projects 20180125 07:38:06< DeFender1031> thanks. 20180125 07:38:21< JyrkiVesterinen> Yw. :) 20180125 07:49:03-!- zookeeper [~lmsnie@wesnoth/developer/zookeeper] has joined #wesnoth-dev 20180125 08:03:02-!- vn971 [~vasya@94.158.103.15] has joined #wesnoth-dev 20180125 08:04:27< vn971> Interesting difference between WML and Lua. In WML, I can write this: 20180125 08:04:27< vn971> `[show_if] x=$x1` 20180125 08:04:27< vn971> In Lua, however, things are different. If I write this: `T.show_if { x = wesnoth.get_variable(x1) }`, the meaning would be totally different. 20180125 08:06:49< vn971> Luckily though, there is also a `lua_function` alternative property there, so no problem in this case. Still, the laziness is interesting thing to keep in mind when porting WML <-> Lua. 20180125 08:34:25-!- travis-ci [~travis-ci@ec2-54-197-145-119.compute-1.amazonaws.com] has joined #wesnoth-dev 20180125 08:34:26< travis-ci> wesnoth/wesnoth#16207 (master - 4a6042a : Gregory A Lundberg): The build has errored. 20180125 08:34:26< travis-ci> Build details : https://travis-ci.org/wesnoth/wesnoth/builds/332884986 20180125 08:34:26-!- travis-ci [~travis-ci@ec2-54-197-145-119.compute-1.amazonaws.com] has left #wesnoth-dev [] 20180125 08:35:11-!- travis-ci [~travis-ci@ec2-54-197-145-119.compute-1.amazonaws.com] has joined #wesnoth-dev 20180125 08:35:12< travis-ci> wesnoth/wesnoth#16206 (master - 09fe1f4 : Alexander van Gessel): The build has errored. 20180125 08:35:12< travis-ci> Build details : https://travis-ci.org/wesnoth/wesnoth/builds/332832011 20180125 08:35:12-!- travis-ci [~travis-ci@ec2-54-197-145-119.compute-1.amazonaws.com] has left #wesnoth-dev [] 20180125 08:37:06< JyrkiVesterinen> The errored builds output this line, then stop giving any output. 20180125 08:37:08< JyrkiVesterinen> 20180124 19:11:41 error desktop: Failed to open DBus session: /usr/bin/dbus-launch terminated abnormally without any error message 20180125 08:38:01< JyrkiVesterinen> https://github.com/wesnoth/wesnoth/blob/b5f76eff796c09921b34baae93989697e07c2ec6/src/desktop/dbus_notification.cpp#L115 20180125 08:40:55< JyrkiVesterinen> Judging from some code reading, the only possibility I see is that dbus_error_free() hangs. 20180125 09:11:51< irker051> wesnoth: Charles Dang wesnoth:master cd937c745c60 / src/editor/controller/editor_controller.cpp: Editor: fixed starting position labels not vanishing immediately when deleted (f https://github.com/wesnoth/wesnoth/commit/cd937c745c6047e5d3e46fc013ea4288d2196b8a 20180125 09:16:46< irker051> wesnoth: Charles Dang wesnoth:master 182b4bb1e5f2 / src/editor/map/map_context.cpp: Editor: don't serialize [side] user_team_name= and [unit] name= if empty (fixes https://github.com/wesnoth/wesnoth/commit/182b4bb1e5f227ba1eaea397781fe8e5e3b00bb8 20180125 09:28:31-!- travis-ci [~travis-ci@ec2-54-197-187-233.compute-1.amazonaws.com] has joined #wesnoth-dev 20180125 09:28:32< travis-ci> wesnoth/wesnoth#16208 (master - 438e021 : Charles Dang): The build has errored. 20180125 09:28:32< travis-ci> Build details : https://travis-ci.org/wesnoth/wesnoth/builds/333145712 20180125 09:28:32-!- travis-ci [~travis-ci@ec2-54-197-187-233.compute-1.amazonaws.com] has left #wesnoth-dev [] 20180125 09:56:25< zookeeper> vn971, the meaning would be totally different... how? 20180125 09:58:44< vn971> zookeeper: well, if I get it correctly, [set_menu_item] will resolve variables x1 and and y1 at the time of testing whether to show the menu. In Lua though, the code `T.show_if { x = wesnoth.get_variable(x1) }` will be evaluated immediately, resulting in a WML equivalet of `[show_if] x = 15` (hard-coded value). 20180125 09:59:27< vn971> in other words, `wesnoth.get_variable` will only be calculated once, because it is never wrappend in a function. 20180125 10:03:27< zookeeper> vn971, right. i guess that makes sense, though? 20180125 10:06:31< vn971> zookeeper: I would not directly answer the question (to avoid being too verbose), but I didn't criticise or anything like that. Just noted the difference. Probably shouldn't to that in a dev channel anyway, as many developers are familiar with these subtle differences anyway. 20180125 10:18:09< Ravana_> same problem with this_unit 20180125 10:18:27-!- aidanhs [~aidanhs@81.4.110.234] has quit [Ping timeout: 240 seconds] 20180125 10:22:57-!- aidanhs [~aidanhs@81.4.110.234] has joined #wesnoth-dev 20180125 10:32:12-!- vladimirslavik [vslavik@nat/redhat/x-owjbhrpvuhxvujis] has joined #wesnoth-dev 20180125 10:44:37-!- travis-ci [~travis-ci@ec2-54-197-187-233.compute-1.amazonaws.com] has joined #wesnoth-dev 20180125 10:44:38< travis-ci> wesnoth/wesnoth#16210 (master - 182b4bb : Charles Dang): The build has errored. 20180125 10:44:38< travis-ci> Build details : https://travis-ci.org/wesnoth/wesnoth/builds/333178255 20180125 10:44:38-!- travis-ci [~travis-ci@ec2-54-197-187-233.compute-1.amazonaws.com] has left #wesnoth-dev [] 20180125 10:45:07-!- JyrkiVesterinen [~JyrkiVest@195-192-251-124.s1networks.fi] has quit [Quit: .] 20180125 10:54:57-!- janebot [~Gambot@unaffiliated/gambit/bot/gambot] has quit [Remote host closed the connection] 20180125 10:55:03-!- janebot [~Gambot@unaffiliated/gambit/bot/gambot] has joined #wesnoth-dev 20180125 12:05:52-!- JyrkiVesterinen [~JyrkiVest@195-192-251-124.s1networks.fi] has joined #wesnoth-dev 20180125 12:17:19-!- irker051 [~irker@uruz.ai0867.net] has quit [Quit: transmission timeout] 20180125 12:34:18-!- janebot [~Gambot@unaffiliated/gambit/bot/gambot] has quit [Remote host closed the connection] 20180125 12:34:28-!- janebot [~Gambot@unaffiliated/gambit/bot/gambot] has joined #wesnoth-dev 20180125 12:36:56-!- irker418 [~irker@uruz.ai0867.net] has joined #wesnoth-dev 20180125 12:36:56< irker418> wesnoth/wesnoth:master Charles Dang 182b4bb1e5 Editor: don't serialize [side] user_team AppVeyor: 1/6 builds failed 20180125 12:36:56< irker418> Details vs2017/Release: https://ci.appveyor.com/project/wesnoth/wesnoth-605wt/build/Wesnoth-VS2017-master-846 20180125 13:08:33< AI0867> 05:36 < DeFender1031> it's the only language I know where "blah = {}; blah[0] = something; blah['0'] = something;" results in two separate keys rather than just one. ← I'm pretty sure you can do that in C++ with either an int map (because '0' == 48) or a variant map 20180125 13:10:54< JyrkiVesterinen> Variants are quite new. Many codebases (including Wesnoth) can't use them yet. 20180125 13:11:33< AI0867> 06:04 < JyrkiVesterinen> BTW, Ruby has one solution to that. A common practice in Ruby code is that any method that modifies the object in-place (for a class that also has copying methods) has a name that ends with an exclamation mark. ← ruby took that from scheme, which took lisp's letter-suffixes and replaced them with punctuation 20180125 13:11:56< vn971> coming from a statically typed world, I'm surprised somebody would expect a string to be auto-converted to int even. Though then again, I don't really use maps that can hold both strings and numbers in said statically typed world. That's all offtopic tho. 20180125 13:13:00< JyrkiVesterinen> Hmm, https://en.wikipedia.org/wiki/Ruby_(programming_language) doesn't list Scheme in the "Influenced by" section. 20180125 13:14:42-!- celticminstrel [~celmin@unaffiliated/celticminstrel] has joined #wesnoth-dev 20180125 13:18:40< AI0867> regarding the dict, python3: 20180125 13:18:46< AI0867> >>> a = {} 20180125 13:18:46< AI0867> >>> a[0] = "int" 20180125 13:18:46< AI0867> >>> a["0"] = "string" 20180125 13:18:46< AI0867> >>> a 20180125 13:18:47< AI0867> {0: 'int', '0': 'string'} 20180125 13:20:10< AI0867> JyrkiVesterinen: maybe it was through an intermediate language? I'm pretty sure scheme came up with the ?! suffixes though 20180125 13:23:42< irker418> wesnoth/wesnoth:master Charles Dang 438e021a27 Editor: exclude some rarely-used keys fr AppVeyor: All builds passed 20180125 13:32:43-!- celticminstrel [~celmin@unaffiliated/celticminstrel] has quit [Quit: And lo! The computer falls into a deep sleep, to awake again some other day!] 20180125 14:02:10-!- stikonas [~gentoo@wesnoth/translator/stikonas] has joined #wesnoth-dev 20180125 14:08:11< vn971> I wonder, can I set a global variable that would NOT be shared with other people over the net, in a multiplayer game? 20180125 14:09:19< vn971> either I don't get something, or there is a strange solution of forbidding local ("offline") globals, and you are forced to query some network state instead. 20180125 14:29:44-!- vslavik [vslavik@nat/redhat/x-dtohwullrrrxegji] has joined #wesnoth-dev 20180125 14:32:15-!- vladimirslavik [vslavik@nat/redhat/x-owjbhrpvuhxvujis] has quit [Ping timeout: 260 seconds] 20180125 14:35:42-!- stikonas [~gentoo@wesnoth/translator/stikonas] has quit [Ping timeout: 265 seconds] 20180125 14:35:45-!- stikonas_ [~gentoo@wesnoth/translator/stikonas] has joined #wesnoth-dev 20180125 15:08:33-!- JyrkiVesterinen [~JyrkiVest@195-192-251-124.s1networks.fi] has quit [Quit: .] 20180125 15:09:08-!- mkdroid [~null@unaffiliated/matthiaskrgr] has joined #wesnoth-dev 20180125 15:34:21-!- stikonas_ is now known as stikonas 20180125 15:38:02-!- mkdroid [~null@unaffiliated/matthiaskrgr] has quit [Quit: I'll be back!] 20180125 15:52:54-!- vslavik__ [vslavik@nat/redhat/x-ufnpsmbotchedcij] has joined #wesnoth-dev 20180125 15:55:10-!- vslavik [vslavik@nat/redhat/x-dtohwullrrrxegji] has quit [Ping timeout: 240 seconds] 20180125 16:10:29< AI0867> TadCarlucci: to restate my question from yesterday: do you think anyone actually used the *base* global based functionality in in wesnoth.unit_types? If not, we should get rid of that ASAP 20180125 16:14:52< TadCarlucci> I do not. And CM's item-list doesn't talk about it. I think it was a mis-guided attempt to do to much at once and his new list is far better. All this is probably new to 1.13 and I'd recommend clean up the global while you're at it. 20180125 16:18:08-!- midzer [~quassel@p5B3120FC.dip0.t-ipconnect.de] has joined #wesnoth-dev 20180125 16:24:52-!- irker418 [~irker@uruz.ai0867.net] has quit [Quit: transmission timeout] 20180125 16:39:03< DeFender1031> AI0867, fair, but that's not entirely what I meant. I meant that it has keys of any type and that int 0 and string 0 result in different keys. 20180125 16:39:47< DeFender1031> AI0867, clever though. 20180125 16:41:43-!- atarocch [~atarocch@93.56.164.28] has quit [Remote host closed the connection] 20180125 16:43:04-!- atarocch [~atarocch@93.56.164.28] has joined #wesnoth-dev 20180125 16:50:13-!- JyrkiVesterinen [~JyrkiVest@85-23-197-3.bb.dnainternet.fi] has joined #wesnoth-dev 20180125 17:10:16-!- Oebele [~quassel@143.177.58.202] has joined #wesnoth-dev 20180125 17:54:54-!- octalot [~steve@178.115.131.232.wireless.dyn.drei.com] has joined #wesnoth-dev 20180125 18:05:54-!- vultraz [uid24821@wesnoth/developer/vultraz] has quit [Quit: Connection closed for inactivity] 20180125 18:07:25-!- boucman [~rosen@wesnoth/developer/boucman] has joined #wesnoth-dev 20180125 18:36:21< JyrkiVesterinen> Initial performance measurements with my "pre-build wesnoth.unit_types" implementation. (It's incomplete, and therefore faster than the final implementation would be.) 20180125 18:36:22< JyrkiVesterinen> 20180125 20:34:50 info scripting/lua: wesnoth.unit_types constructed in 1888 ms 20180125 18:36:42< JyrkiVesterinen> This is with Ageless Era installed and active. Without it, the time is about 98 ms. 20180125 18:37:13< JyrkiVesterinen> That's the one-time penalty every time the player loads a scenario or save file. 20180125 18:40:39< JyrkiVesterinen> I think this is too slow, especially given that this isn't even the full implementation yet. 20180125 18:42:27< JyrkiVesterinen> I'm going to try constructing *the entire table* lazily. Don't initially create the table, but if someone accesses wesnoth.unit_types, create the whole table. On subsequent accesses, direct the caller to the existing table. 20180125 18:55:52< vn971> JyrkiVesterinen: why, essentially, is it slow? What's the slowest part? Still iteration? 20180125 18:56:12< JyrkiVesterinen> I haven't profiled it. 20180125 18:57:55< JyrkiVesterinen> Remember that it's creating and filling a Lua table for every unit type now. 20180125 18:58:21< JyrkiVesterinen> This measurements still means that it's only aking 692 microseconds per unit type, which isn't that much. 20180125 18:58:26< JyrkiVesterinen> *taking 20180125 18:59:47< JyrkiVesterinen> That's definitely a huge improvement compared with master, which needed 14 milliseconds for the same thing. 20180125 19:00:29< JyrkiVesterinen> (Assuming that it was indeed only iterating to the next unit and creating the proxy, and not e.g. recreating other proxies as it went along.) 20180125 19:02:46< vn971> I forgot for a moment how many units there are in Ageless. 20180125 19:04:33< vn971> JyrkiVesterinen: talking about things being lazy. Is there a technical possibility to keep the table keys (of the Lua table) in Lua, but refer to C++ data whenever the value is taken? 20180125 19:06:07< vn971> or no, this is not about anything being lazy. This is about mixing Lua table keys with C++ table values (if such wording is correct, anyway). 20180125 19:08:16< vn971> or is it what you do in the experiment already? I just wonder what's being kept in the hash table: (lua string, lua table) pairs, or (lua string, userdata) pairs? (If the latter thing can exist at all, again, IDK.) 20180125 19:09:11< JyrkiVesterinen> There wouldn't really be any point. 20180125 19:09:49< JyrkiVesterinen> The way iteration works in Lua is that an iterator function is created (either the Lua default, or a custom one). 20180125 19:10:35< JyrkiVesterinen> In every iteration, the iterator function is called, and its return values are assigned to the variables mentioned in the for expression. 20180125 19:11:31< JyrkiVesterinen> I don't know what the bottleneck is in the current implementation in master, but for whatever reason the custom iterator function for wesnoth.unit_types is very slow. 20180125 19:12:17< JyrkiVesterinen> It might be the cost of Lua->C++ call. Finding the next unit in the C++ side. Constructing the proxy. Or something else. 20180125 19:14:51< vn971> JyrkiVesterinen: well yes. The old code is slow because we implement stuff like `next()`. The proposal is to use a Lua table itself for that, but store userdata (direct access to C++ code) in this Lua table-s values. 20180125 19:15:39< vn971> JyrkiVesterinen: in your last experiment, what is `type(wesnoth.unit_types["Mage"])` ? A Lua table (copy), or userdata? 20180125 19:16:06< JyrkiVesterinen> In the code I have locally right now, it's a table. 20180125 19:16:30< vn971> JyrkiVesterinen: the proposal is to store userdata. In a Lua table, yes. 20180125 19:16:34< JyrkiVesterinen> And yes, I get what you mean. wesnoth.unit_types would be a table, but wesnoth.unit_types.Mage would be userdata. 20180125 19:16:44< vn971> JyrkiVesterinen: exactly! 20180125 19:17:13< JyrkiVesterinen> Indeed, that would be one possibility. And probably not even a bad one. 20180125 19:18:29< JyrkiVesterinen> In any case, I wonder why the current implementation (where both are userdata) is ridiculously slow. Such a hybrid model might work well, or it might be slower than my full table approach. 20180125 19:19:50< Ravana_> what approach 1.12 uses? 20180125 19:20:31< vn971> JyrkiVesterinen: my expectation is that hybrid would be the fastest. About the old (current master) approach. I'm most interested by the numbers on how iteration time grows with unit count. 20180125 19:21:41< vn971> JyrkiVesterinen: if you take 10x units, iteration takes about 100x the time. I would speculate that it means that `next()` actually iterates _all_ units to find the "current" one, and then takes next. 20180125 19:22:13-!- vslavik__ [vslavik@nat/redhat/x-ufnpsmbotchedcij] has quit [Quit: Leaving] 20180125 19:22:47< JyrkiVesterinen> vn971: Tad made his own tests, and he observed that the iteration time increased linearly. 20180125 19:23:19< JyrkiVesterinen> That would suggest that it isn't actually iterating all the units (but the iteration times are so long that I find it hard to believe). 20180125 19:23:52< JyrkiVesterinen> Ravana_: 1.12 uses the same model as master, both are userdata. 20180125 19:25:50< JyrkiVesterinen> Personally, I guess that the performance of iteration regressed in https://github.com/wesnoth/wesnoth/commit/b5c5e21895dabbdd0e239968d0d8697c626b72f7 20180125 19:26:54< JyrkiVesterinen> That commit introduced many metamethods for the table. Any of them could have caused the regression. 20180125 19:28:53< vn971> JyrkiVesterinen: would it help to know whether it's the case? (Whether this commit was the one that had iteration speed impact.) 20180125 19:29:24< JyrkiVesterinen> Yes, knowing it would be helpful. 20180125 19:32:21< vn971> // git checkout b5c5e21895dabbdd0e239968d0d8697c626b72f7^ ... 20180125 19:33:22< vn971> though it doesn't build for me. Says > AttributeError: 'module' object has no attribute 'config_checks': 20180125 19:35:11< JyrkiVesterinen> Do you have SCons 3? 20180125 19:36:12< vn971> JyrkiVesterinen: 3.0.1, yes 20180125 19:36:27< JyrkiVesterinen> That explains it. SCons 3 compatibility was implemented later. 20180125 19:42:02< vn971> downgraded scons, but forgot what to do about this > Checking for Ogg Vorbis support in SDL... no 20180125 19:43:12< JyrkiVesterinen> Easiest would be just commenting out the check: https://github.com/wesnoth/wesnoth/blob/master/SConstruct#L382 20180125 20:02:38< vn971> commit b5c5e21895dabbdd0e239968d0d8697c626b72f7^ (parent) is as fast as it gets. Will now try the commit in question. 20180125 20:20:08-!- janebot [~Gambot@unaffiliated/gambit/bot/gambot] has quit [Remote host closed the connection] 20180125 20:20:19-!- janebot [~Gambot@unaffiliated/gambit/bot/gambot] has joined #wesnoth-dev 20180125 20:21:43< vn971> JyrkiVesterinen: you were right, that's indeed the commit where regression starts. 20180125 20:22:10< JyrkiVesterinen> I see. 20180125 20:22:27< JyrkiVesterinen> In that case an alternative fix would be to just remove the offending metamethod(s). 20180125 20:23:05< JyrkiVesterinen> However, celmin added them for a reason, so I'm not sure about how safe that would be. 20180125 20:58:39< Ravana_> seems that location_set must be forced into valid wml table to sync it, and then converted to normal table to set it as wml variable 20180125 21:03:48-!- vn971 [~vasya@94.158.103.15] has quit [Quit: Leaving.] 20180125 21:04:30< Ravana_> location_set has conversion to wml variable, but sync requires wml table 20180125 21:09:17-!- irker678 [~irker@uruz.ai0867.net] has joined #wesnoth-dev 20180125 21:09:17< irker678> wesnoth: Jyrki Vesterinen wesnoth:unit-types-table 34dad0e9458f / src/scripting/ (game_lua_kernel.cpp lua_unit_type.cpp lua_unit_type.hpp): WIP: make wesnoth.unit_types a real table https://github.com/wesnoth/wesnoth/commit/34dad0e9458f7770840afe04ed3fd54c4cc2b9d8 20180125 21:09:17< irker678> wesnoth: Jyrki Vesterinen wesnoth:unit-types-table 7a40574ba0c8 / src/scripting/lua_unit_type.cpp: Restored unit traits, abilities and attacks to wesnoth.unit_types https://github.com/wesnoth/wesnoth/commit/7a40574ba0c861e5131fc8c764922144aadd9b09 20180125 21:21:07-!- JyrkiVesterinen [~JyrkiVest@85-23-197-3.bb.dnainternet.fi] has quit [Quit: Sleep] 20180125 21:23:04< Ravana_> with ipairs not working with wml table, first time I used fori in Lua 20180125 22:19:06-!- travis-ci [~travis-ci@ec2-54-163-26-31.compute-1.amazonaws.com] has joined #wesnoth-dev 20180125 22:19:07< travis-ci> wesnoth/wesnoth#16211 (unit-types-table - 7a40574 : Jyrki Vesterinen): The build has errored. 20180125 22:19:07< travis-ci> Build details : https://travis-ci.org/wesnoth/wesnoth/builds/333462114 20180125 22:19:07-!- travis-ci [~travis-ci@ec2-54-163-26-31.compute-1.amazonaws.com] has left #wesnoth-dev [] 20180125 22:27:02-!- Oebele [~quassel@143.177.58.202] has quit [Remote host closed the connection] 20180125 22:48:09-!- vultraz [uid24821@wesnoth/developer/vultraz] has joined #wesnoth-dev 20180125 22:57:58< irker678> wesnoth: Charles Dang wesnoth:master d11b62590f85 / src/team.cpp: Fixup 3dc8617ec9396 (fixes #2398) https://github.com/wesnoth/wesnoth/commit/d11b62590f855dace22331b70e39454f0346cdb7 20180125 22:58:10-!- zookeeper [~lmsnie@wesnoth/developer/zookeeper] has quit [Ping timeout: 240 seconds] 20180125 23:23:54-!- boucman [~rosen@wesnoth/developer/boucman] has quit [Remote host closed the connection] 20180125 23:33:00-!- mkdroid [~null@unaffiliated/matthiaskrgr] has joined #wesnoth-dev 20180125 23:46:10-!- janebot [~Gambot@unaffiliated/gambit/bot/gambot] has quit [Remote host closed the connection] 20180125 23:46:16-!- janebot [~Gambot@unaffiliated/gambit/bot/gambot] has joined #wesnoth-dev 20180125 23:58:32-!- mkdroid [~null@unaffiliated/matthiaskrgr] has quit [Quit: I'll be back!] --- Log closed Fri Jan 26 00:00:09 2018