Earlier quoted context omitted.
Do you have a link to the source for that? I'm curious to read. If your description is accurate, Rust[1] is exactly what he wants. I've been learning Rust recently (with a little help from [2]) and it does a ton of static code analysis, is safe by default (no dangling or null pointers, no shared mutable state), uses Hindley-Milner type interface just like Haskell, and generally is what you would expect if Haskell and…
He sort of alluded to it, but there's the usual perceived tooling/ retraining/hiring / performance ceiling issues for shops with > N devs, N somewhere between 5 and 25 (I don't agree with his arguments, just repeating them) http://gamasutra.com/view/news/169296/Indepth_Functional_pro... http://www.reddit.com/r/haskell/comments/jap3x/im_very_tempt... http://blogs.uw.edu/ajko/2012/08/22/john-carmack-discusses-t...
John Carmack's comment on Doom 3's code style
201–210 of 210 posts
Re: John Carmack's comment on Doom 3's code style
#202Earlier quoted context omitted.
Some arguments in favour of getters and setters are; that using a function allows for the addition of caching, addition of thread safety checks, changing to compute the variable rather than store it, addition of logging, mapping it to be generated from another variable, etc.
I understand all of those justifications. When I mentioned changing implementation in my post, I was thinking of exactly those sorts of things. But none of them seem to be applied in the general case of "make a pass-through getter and setter for every member variable". My biggest question to the answer of universal getter/setters is "what is being abstracted?" Classes (and objects) are meant to abstract things like a…
Perhaps a lot of people don't like using or writing getters and setters because it's cumbersome if the only code in them is an assignment/return statement. Maybe something like providing Ruby's attr_reader/attr_writer/attr_accessor to create these boilerplate getters and setters is what is required. Also in Ruby all member variables are private, so methods are always needed to access them.
Re: John Carmack's comment on Doom 3's code style
#203Earlier quoted context omitted.
Your up fornt example isn't a result of poor style it's the result of a bad programmer. Assigning the right values to the right variables is the most basic of programming concepts. Sure typo's and bugs happen, I've done it too but it's still a programmer error not style error.
Any style that encourages errors is a bad style. Yes, it's possible to make the code correct and still use up-front declarations. It's also possible to make the code correct while using a 10k-line main() littered with gotos. It's still a very poor programming style. People make mistakes. Practices should be built around this fact, not built assuming people could be perfect if they just tried a little harder.
With one caveat: Heavy constructor/destructor use requires it.
Re: John Carmack's comment on Doom 3's code style
#204Earlier quoted context omitted.
Any style of programming can look like a mistake if you take it to crazy extremes. I find header/template C++ programming works very well provided you do it in moderation and keep things simple. Remember the STL is complicated because it tries to be super generic, and it tries to be super generic because it's a library so it tries to cater for all possible uses. If you're writing a program instead of a library, you c…
For other examples of crazy extremes, see : Java Swing using anonymous classes to 10 or more depths to represent callbacks because OOP and inheritance > all. Haskell having one file IO operation a thousand feet below the surface of a program "un-purifying" the entire call stack with side effects because pure functional is king. Trying to implement any generic anything in C, because in procedural having template or in…
And that's the way it should be. (Refator your programme, if you want to keep the other functions pure. But it is a Good Thing (TM), that you can not hide your IO if you pile on enough layers.) Haskell has other problems, though.
Re: John Carmack's comment on Doom 3's code style
#205Earlier quoted context omitted.
Haskell is a special beast, in the sense that it uses single letters a lot for generic types in signatures. Eg: doFoo :: a -> a where doFoo will take any type a and return something of the same type. Due to the density of the language, you'll often find plenty of small, commented functions.
Compare doubleCompose binary_func transformation first_arg second_arg = binary_func (transformation first_arg) (transformation second_arg) vs doubleCompose (b -> b -> c) -> (a -> b) -> a -> a -> c doubleCompose (+) f x y = (f x) + (f y) (also known as the `on` function). There's hardly any good names for x and y, since they can be anything at all.
Re: John Carmack's comment on Doom 3's code style
#206Earlier quoted context omitted.
I'm kind of the same opinion as Carmack re: getters/setters. My feeling is, if all you're going to do is allow clients to read and write the variable, why not just expose it? Sure, you can argue encapsulation and even justify it by saying that later down the road you may want to change the implementation, but far too often I've seen C++ classes with a setter and getter for every variable, for no good reason (eg, they…
One (maybe stupid?) reason why I really like getter/setters has nothing to do with encapsulation, but that it makes it easier to search for places where a variable is changed. Often you have lots of getFoo and little setFoo functions - so just searching for "Foo" will return lots of results while "setFoo" helps me finding those faster.
Re: John Carmack's comment on Doom 3's code style
#207Earlier quoted context omitted.
Any style that encourages errors is a bad style. Yes, it's possible to make the code correct and still use up-front declarations. It's also possible to make the code correct while using a 10k-line main() littered with gotos. It's still a very poor programming style. People make mistakes. Practices should be built around this fact, not built assuming people could be perfect if they just tried a little harder.
Have you ever seen a bug caused by this? I haven't. At least anecdotally, this is purely stylistic, and has no impact outside of personal preference. With one caveat: Heavy constructor/destructor use requires it.
Not sure what you mean about "heavy constructor/destructor use" requiring this style.
Re: John Carmack's comment on Doom 3's code style
#208Earlier quoted context omitted.
void up_front_decls() { float some_var; int another_var; some_var = get_some_var(); do_some_calculations(some_var); maybe_something_else(&some_var); some_var = get_another_var(); do_some_other_calculations(another_var); blah_blah_already_broken(); } void as_needed_decls() { float some_var = get_some_var(); do_some_calculations(some_var); maybe_something_else(&some_var); int some_var = get_another_var(); // compile-ti…
I would argue that if declaring up-front versus declaring as-needed makes a significant difference in readability, then your functions are too long.
for (int i = 0; i
vs. int i;
// Half a dozen lines
for (i = 0; i
makes a big difference to me.Re: John Carmack's comment on Doom 3's code style
#209Earlier quoted context omitted.
"a function can still be pure even if it calls impure functions, as long as the side effects don’t escape the outer function" This is a very good point that probably could be systematically exploited. Does anyone know examples of this?
In Haskell there is the ST monad can be used to write stateful implementations for pure functions. The type system guarantees that side effects can't escape their scope. http://www.haskell.org/haskellwiki/Monad/ST
Come to think of it, restricting mutable access to only the relevant objects as per function call using const seems to allow just this!
A function having only const input and output "should be" free of side effects (if no global mutables); while still being allowed to run all manner of unpure processes local to its own calling context.
Re: John Carmack's comment on Doom 3's code style
#210Earlier quoted context omitted.
One (maybe stupid?) reason why I really like getter/setters has nothing to do with encapsulation, but that it makes it easier to search for places where a variable is changed. Often you have lots of getFoo and little setFoo functions - so just searching for "Foo" will return lots of results while "setFoo" helps me finding those faster.
Most editors with an indexer solves that automatically with "find all references" . They can usually even order by "read occurrences" and "write occurrences"