10 Mar, 2010, Deimos wrote in the 41st comment:
Votes: 0
I'm used to sigils because I work with PHP/Perl all day. I can see how it would be annoying to some, though.
10 Mar, 2010, Tonitrus wrote in the 42nd comment:
Votes: 0
Before I started using python, its indentation irritated me conceptually, but when I started using the language, I didn't really even notice it. It's how I would have indented anyway, and the forcing of indentation removes a lot of stupid indentation situations that can lead to errors, since the actual indentation affects flow control. That said, the indentation thing can be incredibly irritating if you have a habit of intermixing tabs and spaces, which I do for some reason. I've mostly avoided this issue by setting up vim to space on tabs. (And when that doesn't work, :%s/\t/ /gc does.)
10 Mar, 2010, David Haley wrote in the 43rd comment:
Votes: 0
The only reason that indent-as-block bugs me now (after getting over my initial and completely irrational "zomgwtf I hate you for dictating how I indent anyway" reaction) is that when you have long enough blocks, it can sometimes be hard to differentiate blocks without the block terminator symbol. Yes, you should generally avoid having blocks that long, but, well, yeah.


EDIT: and yes, I have vim only ever insert spaces. I really dislike mixed tabs and spaces, so I just use spaces.
10 Mar, 2010, Deimos wrote in the 44th comment:
Votes: 0
David Haley said:
The only reason that indent-as-block bugs me now (after getting over my initial and completely irrational "zomgwtf I hate you for dictating how I indent anyway" reaction) is that when you have long enough blocks, it can sometimes be hard to differentiate blocks without the block terminator symbol. Yes, you should generally avoid having blocks that long, but, well, yeah.


EDIT: and yes, I have vim only ever insert spaces. I really dislike mixed tabs and spaces, so I just use spaces.

That difficulty can be pretty easily mitigated at the editor level. For instance, Komodo Edit (what I use most of the time) has indentation lines, which are faint, dotted lines for each level of indentation that, when your cursor is near a block delimiter, highlight individually to clarify the block in context. It's actually one of my favorite features. I'm not sure about what other editors/IDEs support it, though.

Also, using spaces to indent is "dictating how I indent anyway", if you're working on a project with more than one developer. At least that's my main gripe with it. I'll spare you the other zealous rants about tab superiority :wink:
10 Mar, 2010, David Haley wrote in the 45th comment:
Votes: 0
deimos said:
That difficulty can be pretty easily mitigated at the editor level. For instance, Komodo Edit (what I use most of the time) has indentation lines, which are faint, dotted lines for each level of indentation that, when your cursor is near a block delimiter, highlight individually to clarify the block in context. It's actually one of my favorite features. I'm not sure about what other editors/IDEs support it, though.

It's not just counting indent levels, it's getting an immediate visual block cue. It's quite possible that this is simply due to having programmed for so long in languages that have explicit block markers; I think that basically every language I've used seriously other than Python has block markers.

deimos said:
Also, using spaces to indent is "dictating how I indent anyway", if you're working on a project with more than one developer. At least that's my main gripe with it. I'll spare you the other zealous rants about tab superiority :wink:

Do you mean using spaces instead of tabs? It understands tabs as well. And actually, it has several heuristics to understand mixed tabs and spaces, although personally I wouldn't trust that too much.
10 Mar, 2010, Deimos wrote in the 46th comment:
Votes: 0
David Haley said:
It's not just counting indent levels, it's getting an immediate visual block cue. It's quite possible that this is simply due to having programmed for so long in languages that have explicit block markers; I think that basically every language I've used seriously other than Python has block markers.

The whole purpose of the indentation line highlighting is to give immediate visual cues. See here.

David Haley said:
Do you mean using spaces instead of tabs? It understands tabs as well. And actually, it has several heuristics to understand mixed tabs and spaces, although personally I wouldn't trust that too much.

Yes, I was talking about the practice of using spaces instead of tabs (not anything to do with Python).

[rant]
If you have your editor place X spaces into your source for each indentation level, then when I open the source in my editor, you have successfully forced me to view the code at your preferred block depth, be that 2, 4, 8, or whatever # of characters. If my preferred block depth is 2 characters because I develop on a tiny terminal, and you use 8 spaces for a tab because you have a 92" LCD running 2345675x2323445 resolution, you're going to make it very frustrating for me to work on that code. Some editors can run through the source and convert X repeated spaces into a tab when you open files, but then you're forcing me to use an editor that I may not want to use just to have your code be readable in my environment. Tab characters were invented to solve this problem. I've yet to hear a compelling argument for why using spaces instead of tabs is a Good Thing.
[/rant]
10 Mar, 2010, David Haley wrote in the 47th comment:
Votes: 0
deimos said:
The whole purpose of the indentation line highlighting is to give immediate visual cues. See here.

Err, yes, but there it's obvious anyhow because of the block indicator. Perhaps such a thing could exist without the block indicator, although it's hard to believe that a text editor like vim could display it.

deimos said:
If you have your editor place X spaces into your source for each indentation level, then when I open the source in my editor, you have successfully forced me to view the code at your preferred block depth, be that 2, 4, 8, or whatever # of characters. If my preferred block depth is 2 characters because I develop on a tiny terminal, and you use 8 spaces for a tab because you have a 92" LCD running 2345675x2323445 resolution, you're going to make it very frustrating for me to work on that code. Some editors can run through the source and convert X repeated spaces into a tab when you open files, but then you're forcing me to use an editor that I may not want to use just to have your code be readable in my environment. Tab characters were invented to solve this problem. I've yet to hear a compelling argument for why using spaces instead of tabs is a Good Thing.

A pretty simple example is making sure that things line up. Imagine I do the following, where an underscore represents a space:

____function_call(arg1, arg2,
__________________arg3)

If you get clever and treat four spaces as tabs, and your tabwidth is anything other than 4, this will get completely screwed up. Using spaces guarantees that it will always line up.

The only way to get this to work when mixing tabs and spaces is to guarantee that you never, ever convert 4 spaces to tabs.

I think that using tabs to indicate left-most indentation is quite sensible, for the reason you gave. But the practical difficulties of making that work across editors etc. far outweigh the gain of letting every last person choose exactly how many spaces they want on their personal code display. You Live With It, like you live with a lot of stuff in any shared coding environment.

Frankly, tabs vs. spaces are the least of the issues you need to deal with when it comes to agreeing upon a common style with many developers…
10 Mar, 2010, flumpy wrote in the 48th comment:
Votes: 0
Coming from a strongly typed, highly block delimited language where indenting WITH delimiters is hard to read when done badly, I could possibly not bear to use python I'm afraid ;(
10 Mar, 2010, Deimos wrote in the 49th comment:
Votes: 0
David Haley said:
A pretty simple example is making sure that things line up.

That's a good example of how space-indentation could be useful, but not for why it should be used instead of tabs. If half of your source is off my screen to the right, that poses a much larger disadvantage than your function arguments not lining up :wink:

David Haley said:
I think that using tabs to indicate left-most indentation is quite sensible, for the reason you gave. But the practical difficulties of making that work across editors etc. far outweigh the gain of letting every last person choose exactly how many spaces they want on their personal code display. You Live With It, like you live with a lot of stuff in any shared coding environment.

Difficulties of making tabs work across editors? Please clarify, because I'm pretty sure tabs and editable tab stops have been de facto text editor features since the invention of text editors, AFAIK.

David Haley said:
Frankly, tabs vs. spaces are the least of the issues you need to deal with when it comes to agreeing upon a common style with many developers…

Sigh. Sad, but true.
10 Mar, 2010, David Haley wrote in the 50th comment:
Votes: 0
flumpy said:
Coming from a strongly typed, highly block delimited language where indenting WITH delimiters is hard to read when done badly, I could possibly not bear to use python I'm afraid ;(

What do you mean?

deimos said:
That's a good example of how space-indentation could be useful, but not for why it should be used instead of tabs. If half of your source is off my screen to the right, that poses a much larger disadvantage than your function arguments not lining up :wink:

Well, if we're talking about clever IDE features anyhow, presumably your IDE can deal with stuff overflowing to the right. :wink:

deimos said:
Difficulties of making tabs work across editors? Please clarify, because I'm pretty sure tabs and editable tab stops have been de facto text editor features since the invention of text editors, AFAIK.

Editor setups might have been a better term than the programs being used (because indeed, chances are extremely high that each program will be able to do something reasonable with tabs vs. spaces). I meant it as in individuals' configuration settings for their editors of choice.
10 Mar, 2010, Deimos wrote in the 51st comment:
Votes: 0
David Haley said:
Well, if we're talking about clever IDE features anyhow, presumably your IDE can deal with stuff overflowing to the right. :wink:

Hah. One or two wrapped lines here and there isn't a big deal, but the kind of line-wrapping you're talking about with, say, 4-5 levels of 8-space indentation on an 80 character terminal would make editing most code practically unbearable.

David Haley said:
Editor setups might have been a better term than the programs being used (because indeed, chances are extremely high that each program will be able to do something reasonable with tabs vs. spaces). I meant it as in individuals' configuration settings for their editors of choice.

Hmm. Are you confusing the tab/space replacement option with the actual tab stop option? Editors can alter a tab character's width without replacing them with spaces. This is, again AFAIK, universal text editor behavior.
10 Mar, 2010, David Haley wrote in the 52nd comment:
Votes: 0
deimos said:
Hah. One or two wrapped lines here and there isn't a big deal, but the kind of line-wrapping you're talking about with, say, 4-5 levels of 8-space indentation on an 80 character terminal would make editing most code practically unbearable.

Well, I suppose so. But on the other hand, if you're working in a shared environment to begin with, presumably you would get relatively sane conventions for the group, such that you wouldn't run into problems like this. For example, 8 spaces per indentation level is really quite a lot, and isn't something I've seen for a long time. Another convention is that lines are to be broken up at some length – oh, and that's a place where the alignment I spoke of actually makes a huge difference. If you align your stuff using tabs and I do it using spaces, things get completely borked very quickly.

deimos said:
Hmm. Are you confusing the tab/space replacement option with the actual tab stop option? Editors can alter a tab character's width without replacing them with spaces. This is, again AFAIK, universal text editor behavior.

I'm not sure why you think I'm confusing anything; I'm referring to how different editors are or can be configured to use spaces and/or tabs in different contexts and to even replace tabs they find with spaces as you edit lines etc.
Basically, the point is that when multiple people are working on source each with their own editor settings for tabs and spaces, the practical difficulties become large very quickly.
10 Mar, 2010, flumpy wrote in the 53rd comment:
Votes: 0
@dh

I mean I would probably get very annoyed with myself and others mistakes when formatting my code.

Plus I'd miss my little curly friends… I practically force people to use then in my team and if I see if statements without them a frowny face goes in the code review :(
10 Mar, 2010, Deimos wrote in the 54th comment:
Votes: 0
David Haley said:
Well, I suppose so. But on the other hand, if you're working in a shared environment to begin with, presumably you would get relatively sane conventions for the group, such that you wouldn't run into problems like this.

Conventions like… not allowing your editor to replace tabs with spaces? :lol:

David Haley said:
I'm referring to how different editors are or can be configured to use spaces and/or tabs in different contexts and to even replace tabs they find with spaces as you edit lines etc.
Basically, the point is that when multiple people are working on source each with their own editor settings for tabs and spaces, the practical difficulties become large very quickly.

If you're working with others, you simply all turn off the tab/space replacement options in your editors and let tabs do the job they were meant to do. Difficulties only arise when Joe in the cubicle down the hall refuses to do this because he's more concerned with lining up his function arguments. :wink:
10 Mar, 2010, shasarak wrote in the 55th comment:
Votes: 0
Here's another example I find useful when thinking about language choice. Suppose a player character is hit by a strength-draining spell which divides his strength by 2 for the next 5 ticks. One tick later, in an attempt to mitigate the effect, he swallows a strength potion which increases his strength by 3 for the next 6 ticks. How do you model this so as to ensure that nothing weird happens as a result of the two magical effects wearing off in a different order from the one they took effect in?

A very primitive approach would be to have the player character's strength simply be a stored number whose value can be returned at any time. The spell would divide that number by two, then, after a set amount of time, double it again. But this clearly doesn't work at all in the above example - otherwise, if the player begins with a strength of 10 he would end up with a strength of 13 at the end when both effects have worn off. (10 halves to 5, add 3, double, subtract 3).

So clearly you can't simply store the player's current strength as a number. Instead, whenever you ask the character object for its strength, a dynamic calculation has to be done: in this case you return (base strength / 2) + 3 while both magical effects are active.

But (and this is the important question) how do you do this in a way which doesn't violate encapsulation? For this to work nicely, the strength potion should not have to allow for the possibilty of the weakening spell being active in order to determine its effect. Similarly, the spell needs to work in such a way that it doesn't need to know about the existence of strength potions. And finally, and most importantly, the code in the Character class should not have to be aware of the possibility of strength modification effects: if it is written in such a way that it anticipates this, then that means the character class has to be modified and extended for every possible effect you might want to add; so no new effects can be added without modifying any class that could be affected by it, and you get massive bloat in target classes to allow for all the things that might happen to them.

One possible solution to this is (again) to use proxies. First, let the spell effect inherit from an Effect class which specifies that any subclass must identify one or methods whose execution will be affected by it. Wrap the character object up in a proxy. The proxy maintains a dictionary; the keys of the dictionary are method names, and the values are lists of all currently active effects that in any way influence the result of invoking that method on the character. So, when you create the weakness spell, you identify it as an effect which influences the result of calling the #strength method on something. When cast, you add the spell effect to the proxy's dictionary.

The next time something asks the character (or rather its proxy) for its strength score, the proxy begins by fetching the character's unaffected strength score directly. It then checks to see if it has any effect objects that affect strength; it finds it has one; it therefore evaluates the strength method on the spell effect, passing in the unaltered value from the character as an argument. If the proxy is in fact tracking multiple effects that influence strength, then the result of each effect's strength evaluation is fed into the next effect (so only the first one is fed the unaltered value obtained from the character). The eventual result that the proxy returns is the character's dynamically calculated strength, allowing for all active effects.

When a spell wears off, the effect is simply removed from the proxy.

Handling things this way means that absolutely nothing except an effect that modifies strength has to be aware that modifying strength is even a possibility, and no one effect has to allow for the possibility of others being active; and even the proxy simply understands the general notion that there are such things as effects, it makes no assumptions at all about what those effects might do.

The idea can be extended by introducing slightly different types of effects which don't merely modify a value returned from a method on the target, they perform actions either before or after (or in some cases instead of) actions taken by the code in the target class.

If you have a system like this then absolutely any aspect of the behaviour of any object can be modified in any way you like, dynamically, instance by instance, without the target needing to know about the possibility of it happening; this allows loads of flexibility for new effects to be added without having to rewrite the classes they act on. Which I think is pretty cool.
:smile:

(As an aside, I'd be intererested to hear how you might achieve something like this in a statically typed language).
10 Mar, 2010, David Haley wrote in the 56th comment:
Votes: 0
This is easy to implement in a statically typed language. You don't even need the proxy business in a dynamic language if you don't want to. Right off the top of my head – and so this might have issues – define a mapping from attribute name to list of effects on that attribute. (If an effect affects several things, it would be in several lists.) An effect contains a callback function that takes the value of the attribute and returns the affected value of that attribute. When you ask a character for the value of some attribute, you first get the attribute from its attribute map, then you apply ("reduce") that value through the chain of relevant effect callback functions.

In this case, the only thing that has to know that modifying attributes is possible is the character (or the proxy), and of course the individual effects that modify the things in question.

Of course this makes assumptions about how you store attributes, but there's no requirement that statically typed languages store attributes as actual variables on the structure, and not in a map from attribute name to attribute value.

If you have a hard list of attributes (like members of a struct) then things still don't change that much; you could still use the above approach and just translate to the name when appropriate, or store hard-coded lists of effect callbacks per attribute, etc.

Now, if you want to take the "augmented" version such that any possible method call can be screwed with by any possible thing, then you'd be basically reimplementing proxies in your statically typed languages and would not call methods the normal C++ way but by giving the name of the operation you're trying to call. But in a sense that's good in its way, because that lets you define straight away which properties/accessors are in fact overrideable. I might not want random people to be able to screw with the meaning of arbitrary methods, after all.
10 Mar, 2010, flumpy wrote in the 57th comment:
Votes: 0
You can write dynamic or static proxies in Java, dynamic ones using reflection.
In fact, CGLib is a dynamic proxy lib and both spring and groovy (I think) use it to do just what you are saying.
I'm on my mobile device so I'm not going to give code examples, just google dynamic proxy Java for some.
10 Mar, 2010, shasarak wrote in the 58th comment:
Votes: 0
David Haley said:
Now, if you want to take the "augmented" version such that any possible method call can be screwed with by any possible thing, then you'd be basically reimplementing proxies in your statically typed languages and would not call methods the normal C++ way but by giving the name of the operation you're trying to call. But in a sense that's good in its way, because that lets you define straight away which properties/accessors are in fact overrideable. I might not want random people to be able to screw with the meaning of arbitrary methods, after all.

But being able to do that is the whole point! :smile:
10 Mar, 2010, Deimos wrote in the 59th comment:
Votes: 0
Why can't it be handled properly using a modified/unmodified attribute?

No effects (20/20)
He gets hit by the spell (20/20)
Tick (10/20) – 20 / 2 = 10
He drinks the potion (10/20)
Tick (8/20) – 10 / 2 + 3 = 8
Tick (7/20) – 8 / 2 + 3 = 7
Tick (6/20) – 7 / 2 + 3 = 6, integer division
Tick (6/20) – 6 / 2 + 3 = 6
Tick (23/20) – 20 + 3 = 23, spell wore off
Tick (20/20) – 20 = 20, potion wore off
10 Mar, 2010, David Haley wrote in the 60th comment:
Votes: 0
Your notation doesn't make much sense to me, sorry.

Using modified/unmodified values is a good way to get you back to the correct original, but it doesn't at all guarantee that you get the right result in the meantime. Shasarak explained this already, although he only spoke of the end result. It should be pretty clear that even if you fix the end result, the intermediate results can be screwed up. For example, you are doubling a value that has already been modified by the +3, instead of removing the halving before the +3.

2 * (x/2 + 3) is obviously entirely different from 2*(x/2) + 3. The former is x + 6 whereas the latter is x + 3. (And then integer division gives you some fun, too.)
40.0/159