--- Log opened Tue Oct 16 00:00:42 2018 20181016 00:02:10-!- celmin|sleep is now known as celticminstrel 20181016 04:18:37-!- celticminstrel is now known as celmin|sleep 20181016 07:11:37-!- zookeeper [~lmsnie@wesnoth/developer/zookeeper] has joined #wesnoth-umc-dev 20181016 10:44:11-!- hk238 [~kvirc@unaffiliated/hk238] has joined #wesnoth-umc-dev 20181016 10:44:16< hk238> hi 20181016 11:51:49-!- vn971 [~vasya@94.158.103.15] has quit [Quit: Leaving.] 20181016 12:58:22-!- celmin|sleep is now known as celmin|away 20181016 16:05:50<+wesdiscordbot> hk238, regarding our earlier debate about for_each_index(), I ran into this blog post: https://blogs.msdn.microsoft.com/ericlippert/2009/05/18/foreach-vs-foreach/ 20181016 16:06:40<+wesdiscordbot> Microsoft explicitly decided to not offer such a method in the .NET Framework, mostly because they worried it would be misused. 20181016 16:18:32< hk238> cool I'll look into that article 20181016 16:21:07< hk238> it doesn't touch a lot upon our discussion it seems, however it does bring up some of the arguments, like having side-effects 20181016 16:21:21< hk238> which are also part of the reasons why I thought it would be worthwhile 20181016 16:22:08< hk238> also it seems to concern not with the structure of having a 'foreach' type of thing but rather different syntax for it 20181016 16:22:48<+wesdiscordbot> The side eeffect issue is exactly why I think for_each_index() is not worthwhile. Because it relies exclusively on side effects, it's not functional programming. It's just an alternative way to write a traditional loop. 20181016 16:22:54<+wesdiscordbot> *effect 20181016 16:24:27< hk238> well we seem to agree on at least some of the fundamental properties of the issue 20181016 16:24:57< hk238> the structure implies sort of non-functional principles, as the method or function is not returning anything, that implies side-effects 20181016 16:25:18< hk238> however doing the same things without a 'side-effecting method' would imply doing those same things with a 'side-effecting loop' 20181016 16:25:45< hk238> and I think it's even worse 20181016 16:26:29<+wesdiscordbot> Whereas I think it's better. Code that relies on side effects should look like it, rather than attempt to hide under a pseudo-functional disguise. 20181016 16:27:07< hk238> oh so you mean it's not good to have an explicit way of labeling non-functional functionality, but instead it's better to package it inside an obscure for loop? 20181016 16:28:12<+wesdiscordbot> What do you mean "obscure"? 20181016 16:28:19< hk238> but it's a corner case, like I think the net benefit, as mentioned in the article, is almost non-existent. So I kind of feel like it's a strawman 20181016 16:28:21<+wesdiscordbot> foreach(Foo foo in foos){ statement involving foo; } 20181016 16:28:27<+wesdiscordbot> foos.ForEach((Foo foo)=>{ statement involving foo; }); 20181016 16:28:43< hk238> notice that the article is not arguing the use of for loops 20181016 16:28:45<+wesdiscordbot> In which way, exactly, is either of these "more obscure" than the other? 20181016 16:28:50< hk238> but rather whether they should be functions, or methods 20181016 16:29:58< hk238> although I guess foo in foos, implies an iterator like a loop, but they're both using a function named foreach, in one it's amethod of foos, in the other it's a function in some other place 20181016 16:30:24<+wesdiscordbot> Either way, it's just boilerplate. 20181016 16:30:40< hk238> also while I like having discussions with you about this, I think it's the like weakest example of a higherorder function, and so I can admit that it's not particularly useful 20181016 16:30:47<+wesdiscordbot> The difference is that traditional foreach is well-known by every existing C# programmer. 20181016 16:31:38<+wesdiscordbot> "Implies an iterator" is irrelevant. The programmer is simply going to know "this loops over all objects in the collection". 20181016 16:32:03< hk238> if that part is irrelevant then.. I don't see what your point is 20181016 16:32:18< hk238> I'm not making a case that foreach should be a method of tables instead of a function 20181016 16:32:59< hk238> I'm making the case that it's better to have an expression like for each, which does all that side-effecting business in a structured manner and also signals that to the user or programmer by having some sort of lable 20181016 16:32:59<+wesdiscordbot> My point is simple. for_each_index() has no advantages at allif you call it with an anonymous function. 20181016 16:33:02< hk238> *label 20181016 16:33:22< hk238> that's the corner case of the cornercase, I can agree with that 20181016 16:33:41<+wesdiscordbot> "Does all that side-effecting business in a structured manner"?! It's the function you pass that has side effects. 20181016 16:33:52<+wesdiscordbot> The loop itself does not have any side effects. 20181016 16:34:22< hk238> that's true, we're talking about implied side-effects 20181016 16:34:29< hk238> for loop doesn't have side-effects either 20181016 16:34:53< Ravana_> foreach function is useful if you can call it with method reference 20181016 16:35:11<+wesdiscordbot> Ravana_: I agree with that. 20181016 16:35:21< hk238> if you have an array like which contains the amount of money people have 20181016 16:35:29< hk238> and thne you want to find out how much money they have in total 20181016 16:35:56< hk238> I think it would be an extremely bad structure to do something like foreach item in array, modify this outside variable 20181016 16:36:12< Ravana_> summing is most basic use case, usually has sum function 20181016 16:36:13<+wesdiscordbot> I'm surprised that Microsoft decided to go to the lengths of explicitly leaving it out. They probably understood that programmers like hk238 would then call it with anonymous functions, making their code slower and harder to debug. 20181016 16:36:25< hk238> it would be much better to have a function that adds the values and returns it, then you have separate statement where you assign the return value to the total money thing 20181016 16:36:45<+wesdiscordbot> Of course. And for that .NET has .Accumulate() 20181016 16:36:52< hk238> even the person writing the article isn't making the case you're trying to make 20181016 16:37:14<+wesdiscordbot> The difference, of course, is that .Accumulate() is functional whereas .ForEach() isn't. 20181016 16:37:37< hk238> that is certainly the case, implicitly 20181016 16:39:22< hk238> in fact you could say that there being a foreach function in both examples of the article are rather arguments for having one, rather than against, and definitely it's not arguing writing a for loop instead of the foreach expression whether it be a method or not 20181016 16:39:32< hk238> although it does imply an iterator since the argument has foo in foos 20181016 16:40:27< hk238> so on some level it does do that, but still, with in a foreach kind of thing. Which is the worst possible higherorderfunction there is, and calling it with an anonymous function is the worst possible example. Still it's a cleaner structure than a forloop, which is inherently unlabeled, obscure, and might not even terminate 20181016 16:41:45<+wesdiscordbot> "inherently unlabeled": uh, foreach is a keyword that's highlighted in the IDE, whereas .ForEach() would just be a function call among others. .ForEach() is the unlabeled one here. 20181016 16:42:04<+wesdiscordbot> "obscure": Like I said, every C# programmer knows the foreach loop. 20181016 16:43:08<+wesdiscordbot> "might not eve terminate": false. The programmer isn't able to prevent the loop from advancing, other than by invoking an infinite loop (which they can also do with .ForEach). 20181016 16:43:34<+wesdiscordbot> Your criticism towards traditional loops is complete nonsense. 20181016 16:44:07< hk238> umm 20181016 16:44:21< hk238> I have to disagree about that 20181016 16:45:08< hk238> and we've already had this argument 20181016 16:45:13< hk238> the article isn't making the case you're making 20181016 16:45:37<+wesdiscordbot> It's making exactly that case. 20181016 16:45:39< hk238> and it seems pointless. I definitely prefer 'foreach' over 'for loops' 20181016 16:46:09< hk238> no it's not 20181016 16:46:35<+wesdiscordbot> My case is that "calling for_each_index() equivalent with an anonymous function doesn't make any sense". And now I learned that Microsoft agrees with me so strongly that they decided not to offer that function at all! 20181016 16:47:15< Ravana_> you can hide all "if" and "for" statements into functions, but that is not something to aim for - makes code more hidden 20181016 16:47:17< hk238> Microsoft also produced Vista, but okay I accept this as an appeal to mega Authority 20181016 16:48:01<+wesdiscordbot> The article I linked to was written by Eric Lippert (a professional programming language designer), not Steve ballmer. 20181016 16:48:09<+wesdiscordbot> *Ballmer 20181016 16:49:29< hk238> well I might have slightly misunderstood about what kind of thing this foreach is in C# 20181016 16:53:18< hk238> overall it seems to be concerned with the same issues I'm concerned when I decided to make that 20181016 16:53:53< hk238> in that I wanted to have an explicit way of doing something that involves side-effects 20181016 16:54:27< hk238> hmm 20181016 16:54:27<+wesdiscordbot> Strange that your "explicit way" looks much less explicit to me... 20181016 16:57:12< hk238> I definitely prefer this over the lua's loop alternative 20181016 16:58:21<+wesdiscordbot> Fine... if you prefer it, then you can keep using it. In any case, I believe it's harder to understand and doesn't have any advantages. 20181016 16:58:47< hk238> you can believe that if you want to 20181016 16:59:30< hk238> btw is the example valid C# in the article? "foreach(Foo foo in foos){ statement involving foo; }" like that? 20181016 16:59:52<+wesdiscordbot> Yes, it is. 20181016 17:00:19< hk238> overall I think the case in the article is a bit stronger 20181016 17:00:28< hk238> how do you write a lua for loop, I forgot in the meantime? :d 20181016 17:00:33<+wesdiscordbot> The second example isn't valid because .ForEach() doesn't exist, but it can be made valid by writing a one-line extension method. 20181016 17:01:08< hk238> right 20181016 17:01:13< hk238> https://www.lua.org/pil/4.3.4.html 20181016 17:01:42<+wesdiscordbot> for _, foo in ipairs(foos) do {statement involving foo} end 20181016 17:01:49< hk238> https://www.lua.org/pil/4.3.5.html 20181016 17:01:54< hk238> I guess this was the main poin tof comparison 20181016 17:01:58<+wesdiscordbot> (Brances aren't needed, but I put them in for readability. 20181016 17:02:00<+wesdiscordbot> ) 20181016 17:03:01< hk238> well I do think the lua generic for loop is messier syntactically and also slightly more difficult 20181016 17:03:20<+wesdiscordbot> Hmm, I see your point. 20181016 17:03:32< hk238> it also is confusable with the numeric for in the previous page 20181016 17:04:01<+wesdiscordbot> I think it's still not a big problem beecause generic for loops are Lua 101, but whatever. ¯_(ツ)_/¯ 20181016 17:04:10< hk238> :D 20181016 17:04:33< hk238> yeah I can agree with the microsoft case about C# to some extent 20181016 17:04:52< hk238> both examples achieve succesfully labeling something bad, as in side-effects 20181016 17:05:17< hk238> and I guess if you use for loops of the generic type, only for iterating arrays in a manner that's similar to the foreach statement 20181016 17:05:32< hk238> then I guess the generic for loop structure then gains the signal that it's side-effecting 20181016 17:05:46< hk238> I'm not sure I'm confused 20181016 17:06:02<+wesdiscordbot> " both examples achieve succesfully labeling something bad, as in side-effects" I disagree about that... .ForEach() doesn't look like code that has side effects at a first glance, and is highlighted with a different color than the foreach keyword. 20181016 17:06:08< hk238> I've not thought about lua or programming for weeks and ended up forgetting the lua syntax for a loop due to not having write any 20181016 17:06:50< hk238> ah if you don't see it as implying it then.. well I see it that way 20181016 17:07:26<+wesdiscordbot> As a general rule, I think it would be a confusing rule: "A LINQ function doesn't have side effects, unless it's .ForEach()." 20181016 17:08:02< hk238> I agree with that point I guess 20181016 17:08:28< hk238> having a separate type of syntax for something that does have side-effects seems like a good idea 20181016 17:08:53< hk238> and since side-effects are implied by the structure, I can kind of agree with that the function body shoulnd't be someplace else where it's called, if that's where the side-effects are 20181016 17:09:16< hk238> it sort of ends implying having to write an anonymous function, as it would be bad to have an outside function with side effects that's not in the context the programmer is looking at 20181016 17:11:19<+wesdiscordbot> I think "function body somewhere else" is the only case where .ForEach() would make sense. 20181016 17:11:27<+wesdiscordbot> Because it would help avoid code duplication. 20181016 17:11:40< hk238> yeah 20181016 17:11:52<+wesdiscordbot> The same named function could be called for one element, or for all of them with .ForEach(). 20181016 17:12:40< hk238> I'll have some coffee, brb, at least there's a lively discussion if nothing else 20181016 17:12:41< hk238> :D 20181016 17:15:50< hk238> so overall I think this foreach issue is probably the weakest case of a higher order function and I can agree that it doesn't benefit much at all. Especially since it involves most likely writing anonymous functions 20181016 17:16:00< hk238> I'm not sure what to think about this further 20181016 17:16:46<+wesdiscordbot> Yeah, I think it only barely qualifies as a higher order function. A telltale sign is that it doesn't really do anything. 20181016 17:17:34<+wesdiscordbot> The point of higher order functions is to abstract common functionality away. .ForEach() doesn't really have any "common functionality", it just wraps a loop. 20181016 17:18:25< hk238> hm 20181016 17:20:47< hk238> I guess I'll go and look at how I've actually used this 20181016 17:27:19< hk238> I guess they mostly just replace the loops, and I guess I've just used to it by now, when i see the 'for_each_index' words then I think a similar thing as 'for i,v in ipairs(t) do ' 20181016 17:28:15< hk238> but if possible it's better to use functions than loops overall, in this case it doesnt achieve much 20181016 17:29:05< hk238> here I've double forloop written as for_each_index statements 20181016 17:29:28< hk238> https://pastebin.com/SAE0cdJd 20181016 17:30:02<+wesdiscordbot> My eyes! >_< 20181016 17:30:53< hk238> it would probably not be much better with for ipairs thing 20181016 17:31:00< hk238> but of course 20181016 17:31:04< hk238> if you didn't abstract this as a function 20181016 17:31:34< hk238> it would absolutely hideous to have something like that double forloop elsewhere in the code 20181016 17:31:43< hk238> at least that part makes sense 20181016 17:31:54<+wesdiscordbot> It would be easier to read for Lua programmers who aren't familiar with your codebase. And it might also have better performance, function calls have overhead. 20181016 17:32:05<+wesdiscordbot> But I agree that it's not that big an advantage. 20181016 17:33:00<+wesdiscordbot> (With "it", I mean replacing for_each_index(), not inlining the othermost function.) 20181016 17:33:06<+wesdiscordbot> *outermost 20181016 17:33:54< hk238> yes I assumed that's what you meant 20181016 17:34:11< hk238> but then when I'm looking at where I'm calling this.. it's not much better :D 20181016 17:34:19< hk238> "local map_hexes = array_cartesian_product(initialize_array(23, identity), initialize_array(19, identity))" 20181016 17:34:56< hk238> identity function is function identity (x) return x end 20181016 17:35:04<+wesdiscordbot> Maybe identity could be an implied default value for the second parameter? 20181016 17:36:12< hk238> it's because like if I want to initialize an arrya that like squares 1,2,4.. then I can write initialize_array(23, square) instead of having a separate function 20181016 17:36:18< hk238> but it's pretty silly :D 20181016 17:36:58< hk238> it would be much cleaner to have an initialize function that doesn't take a function argument 20181016 17:37:09< hk238> probably a better structure too, now that I think about it 20181016 17:37:25<+wesdiscordbot> ...a default function like I suggested above? 20181016 17:38:10< hk238> You mean I could change the initialize_array function s othat the default value is index? 20181016 17:38:43<+wesdiscordbot> Yes, if the caller doesn't explicitly pass any function. 20181016 17:38:53< hk238> oh yeah that would be better I guess 20181016 17:40:17< hk238> how do I check if the function was supplied as an argument? Although I don't like calling functions with a different number of a parameters than what it expects, that would be more readable without the second argument 20181016 17:40:37< hk238> I guess it's something like, if f then f(x) else x end ? 20181016 17:40:55<+wesdiscordbot> http://www.lua.org/pil/3.3.html 20181016 17:41:06<+wesdiscordbot> "A useful Lua idiom is x = x or v" 20181016 17:41:29<+wesdiscordbot> So, in your case: f = f or identity 20181016 17:42:27< hk238> also when I think about it would probably be better to just have initialize_array then use something like map 20181016 17:42:50< hk238> but then because map is not a method but a function, it implies having parentheses so the expression becomes nested 20181016 17:43:27<+wesdiscordbot> Please clarify. 20181016 17:43:42< hk238> as in initialize_array(23).map(square) would be the method but map(initialize_array(23)) 20181016 17:44:35< hk238> speaking of which can you attach a method to all tables? I was wondering I could attach a lambda method that expects a function and calls it with self 20181016 17:44:35<+wesdiscordbot> Ah, right. I see. 20181016 17:46:11< hk238> I wrote that incorrectly too, coz the square missing from the argument of the second version 20181016 17:46:22< hk238> but I guess you figured that out anyway 20181016 17:46:22< hk238> :D 20181016 17:46:36<+wesdiscordbot> No, you can't define a method that will automatically be added to all tables. 20181016 17:47:29< hk238> I did that with an ircbot to allow writing expressions as a chain (inspired by haskell I guess) 20181016 17:47:39<+wesdiscordbot> You can create object-oriented programming of sorts in Lua where your objects inherit methods from their class... but doing so requires creating the objects in a different way, a simple {} won't do. 20181016 17:48:25< hk238> I like this implicit return self thing with the expressions 20181016 17:48:44< hk238> which allows chaining methods 20181016 17:48:48< hk238> as in the above 20181016 17:49:24<+wesdiscordbot> I have written code in Ruby, where every method implicitly returns the value of its last expression. 20181016 17:49:42<+wesdiscordbot> I felt that it didn't really make things any easier (but it didn't hurt either). 20181016 17:49:54< hk238> perhaps having those on separate lines might makes things clearer though more verbose 20181016 17:51:17< hk238> I mean, without the implicit thing you'd have to write an assign new value statement for each applied method.. 20181016 17:51:17< hk238> :D 20181016 17:51:57< hk238> actually no that's not quite true I got confused again 20181016 17:52:42< hk238> well yes I guess it is true on some level 20181016 17:55:07< hk238> more broadly I suppose it involves the idea of iterative symbol replacement as part of expression evaluation 20181016 17:56:44< hk238> as in if you have "x" it becomes "5" if x is assigned the value 5 before, a function call expression becomes the return value of the function, in functional programming principles methods like map return a new array instead of mutating the old one in place, thus it allows chaining the expressions a.map().map() etc 20181016 17:57:49< hk238> simply by repeating the symbol replacement procedure following syntax with left to right order of associativity.. I mean what it is called 20181016 18:01:46< hk238> but arguably it's cleaner to have t.map(f).map(g).map(h) over map(h,map(g,map(f,t))), but it could also be written as 3 line statements with a working variable 20181016 18:05:10< hk238> anyone want to suggest names for the vampire units in this faction? I'm having trouble deciding what to call them 20181016 18:05:10< hk238> :D 20181016 18:17:15< Ravana_> in java, you can map() only from one-use data structures, such as streams 20181016 23:07:31-!- hk238 [~kvirc@unaffiliated/hk238] has quit [Quit: KVIrc 5.0.0 Aria http://www.kvirc.net/] 20181016 23:46:16-!- zookeeper [~lmsnie@wesnoth/developer/zookeeper] has quit [Ping timeout: 260 seconds] --- Log closed Wed Oct 17 00:00:43 2018