Live data from Hacker News

John Carmack on inlined code (2014)

number-none.com

271–280 of 402 posts

Re: John Carmack on inlined code (2014)

#271
post #79

Earlier quoted context omitted.

Here's the link where he discusses functional programming style: https://web.archive.org/web/20170116040923/http://gamasutra.... He does not say that that his email is completely outdated - he just says that calling pure functions is exempt from the inlining rule. He's not off writing pure FP now. His approach is still deeply pragmatic. In the link above he discusses degrees of function purity. "Pure FP" has a whole…

Thank you for this. I appreciate that this (classic) article lays bare the essence of FP without the usual pomp and "use Lisp/Scheme/Haskell already" rhetoric. My takeaway is that FP is mostly about using functions w/o side effects (pure), which can be achieved in any programming language provided you're diligent about it.

This is a bit naive though. It depends on what you want to do and whether the language you are using offers the required primitives and other things like persistent functional data structures. Without those, you will find yourself hard-pressed to make FP happen. It is of course usually possible with most languages (except those where primitives are already mutating and therefore infectiously prevent you from writing pure functions), but it might not be idiomatic at all, or might not be feasible to roll all things your own, to replace any mutating basics. For example imagine having to copy a data structure all over the place again and again, because its methods are mutating its internal state. That would be inefficient, much more inefficient than a well written corresponding functional data structure, and it would be ugly code.

Are you going to write that extra data structure, when your task is actually something else? Some management breathing down your neck, asking when something will be done? Or not so well versed coworkers complaining about you adding a lot of code that might need to be maintained by them, while they don't understand FP? Do you even have the knowledge to implement that data structure in the first place, or will you need to study a couple of papers and carefully translate their code, if any, i to your language and then verify expected performance in meaningful benchmarks?

Lots of problems can arise there in practice.

Re: John Carmack on inlined code (2014)

#272
post #193

Here are some information theoretic arguments why inlining code is often beneficial: https://benoitessiambre.com/entropy.html In short, it reduces scope of logic. The more logic you have broken out to wider scopes, the more things will try to reuse it before it is designed and hardened for broader use cases. When this logic later needs to be updated or refactored, more things will be tied to it and the effects will b…

This is why I think it's a mistake that many popular languages, including standard c/c++, do not support nested function definitions. This for me is the happy medium where code can be broken into clear chunks, but cannot be called outside of the intended scope. A good compiler can also detect if the nested function is only called once and inline it.

In Java, a local function reference (defined inside a method and never used outside of this method ) is possible. Notre that this function is not really tied to an object, which is why I don't call it a method, and I don't use the expression "method reference", it is just tired to the function that contains it, which may be a method - or not.

Re: John Carmack on inlined code (2014)

#273
post #103

> Inlining functions also has the benefit of not making it possible to call the function from other places. I’ve really gone to town with this in Python. def parse_news_email(…): def parse_link(…): … def parse_subjet(…): … … If you are careful, you can rely on the outer function’s variables being available inside the inner functions as well. Something like a logger or a db connection can be passed in once and then us…

That’s gonna be quite expensive, don’t do this in hot loops. You’re re-defining and re-creating the function object each time the outer function is called.

Good point. I measured it for 10^6 loops:

(1) 40ms for inline code;

(2) 150ms for an inner function with one expression;

(3) 200ms for a slightly more complex inner function; and

(4) 4000ms+ for an inner function and an inner class.

  def f1(n: int) -> int:
      return n * 2

  def f2(n: int) -> int:
      def g():
          return n * 2
  
      return g()
  
  def f3(n: int) -> int:
      def g():
          for _ in range(0):
              try:
                  pass
              except Exception as exc:
                  if isinstance(exc, 1):
                      pass
                  else:
                      while True:
                          pass
                  raise Exception()
          return n * 2
  
      return g()
  
  def f4(n: int) -> int:
      class X:
          def __init__(self, a, b, c):
              pass
  
          def _(self) -> float:
              return 1.23
  
      def g():
          for _ in range(0):
              try:
                  pass
              except Exception as exc:
                  if isinstance(exc, 1):
                      pass
                  else:
                      while True:
                          pass
                  raise Exception()
          return n * 2
  
      return g()

Re: John Carmack on inlined code (2014)

#274

Earlier quoted context omitted.

> he's moved on from inlining and now does pure functional programming Neither of those are true. He does more FP ”where reasonable“, and that decreases the need for inlining. He does not do pure FP, and he still inlines.

"pure FP" does not mean only writing in a functional style. Purity refers to referential transparency, ie., functions do not depend on or modify some global state.

Actually even further: They also don't modify/mutate any arguments. If they did, then that could raise problems with concurrency.

Re: John Carmack on inlined code (2014)

#275

Earlier quoted context omitted.

You can artificially create scope. I often write code like: Foo f = null; { ... stuff with variables f = barbaz; }

Now you have to make `f` nullable and you run the risk of not initialising it and getting a null pointer. You can't do it in C, but in functional style languages you can do this: let f = { let bar = ...; let baz = ...; let barbaz = ...; barbaz }; Which is a lot nicer. But if you ask me it's just a function by another name except it still doesn't limit scope quite as precisely as a function.

GCC and clang (and maybe others) have 'statement expressions': https://godbolt.org/z/sqYnbh4Ej

Re: John Carmack on inlined code (2014)

#276
post #270
post #254

Earlier quoted context omitted.

There is a longer version of this thought-provoking post, also including Carmack's thoughts in 02012, at https://cbarrete.com/carmack.html . But maybe that version has not also had threads about it.

It doesn't seem to have, since https://news.ycombinator.com/from?site=cbarrete.com is empty. Should we change the top link to that URL?

I do think it's a better page, but I wouldn't change the link if I were in charge. On the other hand, I think everyone is grateful that you're in charge of HN and not me. Especially not me. So I think you should use your judgment.

Re: John Carmack on inlined code (2014)

#277
post #2

When I first heard the maxim that an intelligent person should be able to hold two opposing thoughts at the same time, I was naive to think it meant weighing them for pros and cons. Over time I realized that it means balancing contradictory actions, and the main purpose of experience is knowing when to apply each. Concretely related to the topic, I've often found myself inlining short pieces of one-time code that mad…

That’s undoubtedly a Zelda Fitzgerald quote (her husband plagiarized her shamelessly).

As a consequence of the Rule of Three, you are allowed to have rules that have one exception without having to rethink the law. All X are Y except for Z.

I sometimes call this the Rule of Two. Because it deserves more eyeballs than just being a subtext of another rule.

Re: John Carmack on inlined code (2014)

#278

Earlier quoted context omitted.

C++ has lambdas and local classes. Local classes have some annoying arbitrary limitations, but they are otherwise useful.

After spending a lot of time writing idiomatic React components in es6, I've found my love of locally declared lambdas to really grow. If I give the lambdas really good names, I find that the main body of my component is very, very readable, even more so than if I'd used a more traditional style liberally sprinkled with comments.

> If I give the lambdas really good names

That's a really funny way to say it.

Re: John Carmack on inlined code (2014)

#279

> That was a cold-sweat moment for me: after all of my harping about latency and responsiveness, I almost shipped a title with a completely unnecessary frame of latency. In this era of 3-5 frame latency being the norm (at least on e.g. the Nintendo Switch), I really appreciate a game developer having anxiety over a single frame.

You're over-crediting Carmack and under-crediting current game devs. 3-5 frames might be current end-to-end latency, but that's not what Carmack is talking about. He's just talking about the game loop latency. Even at ~4 frames of end-to-end latency, he'd be talking about an easily avoided 20% regression. That's still huge.

Re: John Carmack on inlined code (2014)

#280
post #2

When I first heard the maxim that an intelligent person should be able to hold two opposing thoughts at the same time, I was naive to think it meant weighing them for pros and cons. Over time I realized that it means balancing contradictory actions, and the main purpose of experience is knowing when to apply each. Concretely related to the topic, I've often found myself inlining short pieces of one-time code that mad…

> I was creating inconsistencies that younger developers nitpick

Obligatory: “A foolish consistency is the hobgoblin of little minds"

Continued because I'd never read the full passage: "... adored by little statesmen and philosophers and divines. With consistency a great soul has simply nothing to do. He may as well concern himself with his shadow on the wall. Speak what you think now in hard words, and to-morrow speak what to-morrow thinks in hard words again, though it contradict every thing you said to-day. — 'Ah, so you shall be sure to be misunderstood.' — Is it so bad, then, to be misunderstood? Pythagoras was misunderstood, and Socrates, and Jesus, and Luther, and Copernicus, and Galileo, and Newton, and every pure and wise spirit that ever took flesh. To be great is to be misunderstood.” ― Ralph Waldo Emerson, Self-Reliance: An Excerpt from Collected Essays, First Series

Post reply on HN