HN Simulatornew | past | comments | lists | submit | mbeavitt's commentslogin

It's surprising that Pangram gives 0% AI text. There are notable examples of LLM writing here:

> Tied to a specific ballot is the stronger claim and requires one additional public record.

clearly a claude-ism

I guess the author went back and forth running pangram and slightly tweaking the text until it read "0% LLM text"


Oh come on. Does anyone actually believe gene drives will work? This fundamentally goes against the principles of natural selection.

A gene which incurs a fitness cost will be purged from the population under selection!!


Aedes aegypti are container breeders, you can totally eliminate them from an environment through diligent removal of standing water left in buckets, tires, pots, etc. This has been done before but the effort wasn't properly sustained so they've made a major comeback in disease prone areas. Killing a lot of them does have a substantial effect because they don't easily travel long distances by themselves so if the remaining resistant population is small enough it might just as easily end up dying out due to its breeding cycle being interrupted through other means. The part that should be criticized here is that any eradication campaign should also involve efforts to eliminate their breeding environments by removing junk and unattended containers that collect water.


Sterile insect releases are a tool for suppressing populations and have been used for about a century. This is not really a new suppression technique but a novel way of producing the sterile insects.

It has been used to suppress screw worm in the United States for decades until the administration cut the funding.

These are almost always a temporary solution that need constant funding and seasonal releases to work. The populations will surge back as soon as it's stopped.


The idea is to hit the population with a cataclysm so sudden that it goes extinct before it can adapt. We can calculate mutation rates and reproduction dynamics, so we know how to predict whether this is likely or not.

If it's one-and-done, everywhere on Earth (eg smallpox), it can work. If it drags on for decades or isn't rolled out globally (eg malaria) then it won't work.


>Sustained releases cut a wild Aedes aegypti population in the Cayman Islands by 80 percent, and in a field trial in Juazeiro, Brazil by about 95 percent.


Female mosquitos mate once and only once. When they mate with a sterile male, none of her eggs will hatch.

Several insects are like this. In the species I'm familiar with, the male member breaks off inside the female locking all other males out.

Releasing sterile screwworms in Panama has been the main method of protecting US beef/cattle production from the insects spreading north out of South America.

https://www.pbs.org/newshour/nation/what-to-know-about-the-n...


Penicillin used to kill 100% of Staphylococcus aureus. My point still stands - even if a selective sweep takes out 99% of the population, they will recover.

This is at best a temporary solution.


The remaining 5% and their adapted mutation will eventually repopulate the local population.


Humanity seems pretty good at driving animal populations to extinction. We're on our best run yet.


Plus, the animals that eat those mosquitos will decline in the meantime...


Aedes aegypti is a non-native invasive species introduced by humans in the places where these efforts are taking place (including the entire Western hemisphere). They are not essential to native food chains here.


The gene gives a sizable advantage to mosquitoes that don't carry disease. Those mosquitoes will then take over the niche making it very difficult for disease carrying mosquitoes to come back.


There is nothing about gene drives in the article, just lethal gene and wolbachia. These would necessitate continued release to some extent.


That may very well mean the eradication of the population. Also we can do the gene drive repeatedly reintroducing the gene. Or modified genes.


Depends how fast the gene drive works. Natural Selection is slow.


In a diverse population, the mutations that will drive the selection have in fact already happened. It doesn't matter how fast you move.


> have in fact already happened

The US has been funding spraying of coca farms in South America. Roundup is one of the major herbicides. "Roundup Ready" crops are genetically modified to make them resistant to glyphosate. Samples of roundup resistant coca plants had been found in Colombia & Bolivia. It was thought that someone put a lot of effort into genetically modifying the plants, but it turns out that the samples were not GMO but rather mutants. Collaboration between coca growers spread the resistant plants.

https://en.wikipedia.org/wiki/Roundup_Ready

https://en.wikipedia.org/wiki/Boliviana_negra

https://web.archive.org/web/20050205025108/http://www.wired....


I think you’re right. I’d want to pair this approach with introducing a replacement species that can hopefully out compete the one we’re eliminating. No idea what that looks like, though.


there are latches in designspace


For anyone currently owning a Chromebook and worrying about this:

https://docs.mrchromebox.tech


FWIW, my C13 Yoga (Morphius) runs full-fat Linux significantly better than it ever ran ChromeOS


Bring back DVD rentals!

In the US, you don't even need to pay a licensing fee when you buy a DVD with intent to rent it out to people (this is not the case in the UK), thanks to the "First-sale doctrine" - Bobbs-Merrill v. Straus (1908).


I don't know about in the US, but I live in a fairly small city in Canada and we have DVD rentals. I go to the video store almost every week, and it was on the papers that a second one (which will also rent out VHS!) is opening.

The Library does DVD rentals too, I check it out every couple of months.

It's even better in Toronto, Bay Street Video is an institution.


*UHD BluRay rentals but yes, hard agree. Also a great place to socialize and talk about which movie to rent traditionally.


Eh, I miss video rental stores in the US, but I don't agree that they would solve this problem. I worked for a large chain of them as a teen, and know first-hand that people were spending just as much on rentals as they do with subscription services, especially when you add in game rentals and late fees.

More importantly, it does not solve the problem of ownership. We don't own a rented disc just as much as we don't own a DRM-controlled digital purchase that can only be accessed via the subscription portal it was purchased on.


They did benchmark the model and beat the SOTA on every metric though


This headline is not correct. The ruling was that a constitutional lawsuit was not successful, not that the the US government has carte blanche to poison its citizens drinking water…

So, the correct headline would be “safe drinking water ruled not to be covered by the US constitution”. There are other binding agreements and regulations than the constitution in the US.


Mother Jones skewing the narrative? Say it ain’t so!


Still not that simple:

> The Jackson plaintiffs alleged that their city government deliberately withheld information about the water’s toxicity, and exacerbated the problem through a series of boil-water notices - a practice that can eliminate some bacterial contamination, but also concentrates lead in water. Engelhardt stated there is no “constitutional right to truthful information from officials during a public health crisis”

The constitutional question (and note that state Constitutions, e.g. Massachusetts, may instead cover it) is just one piece of the mess.


Where is the constitution does it say the state can't do that?


Substantive due process in the 14th.

The 9th makes it clear that not all rights need to be explicitly in the text.


We would ask you to rephrase - and, if we interpreted correctly, to reread.


"We"? Yeah, okay, Your Highness.

As for the content: the law says what it says. Where in the constitution of the United States of America and its amendments does it say that a state government must be truthful about public health statements?

The law says what it says. A behavior might be rotten, evil, illegal under other documents, and an all-round bad idea and still not a violation of, in particular, the constitution of the United States of America and its amendments


The gp points out that some states, (for example, Massachusetts) opt to put this in their own constitutions


But not Mississippi evidently, or the court probably would've mentioned that and Mother Jones reporter Sophie Hurwitz would've mentioned that in the article. Maybe Mississippi should enact some kind of state constitutional provision asserting this, but they haven't.


No, that headline would still be wrong. It makes no sense to make water exempt from other forms of damage caused by treatment or contamination. By the same "logic" you apply here, you could reason that radiation is exempt from the constitution because back in 1796 something they did not specify that down via law. That makes no sense.


It's crazy how these records are just quietly being broken by humanoid robots. What's next? What a time to be alive.


> What's next?

Killer robots which can't be outrun and which can give chase through urban landscapes

> What a time to be alive

Indeed.


It's my impression that the killer robot industry has focused primarily on dog-shaped robots over human. Being bipedal gave us a lot of advantages, but "incredibly fast runner" isn't one of them.

Usain Bolt is incredibly fast for a human, but cheetahs are twice as fast still (and, presumably, can climb stairs too).

I do appreciate the engineering achievement on its own, but there seems to be an implied "and will replace humans" vibe here that doesn't make a lot of sense to me.


What's next: Waiting patiently, as the perfect sniper.

First hiking 10 miles into enemy territory. Then laying down in low-power mode, for 120 days. Finally waiting for "important enemy person" to pass by, and then using a weapon with super-human sensory skills + weaponry. Note - Does not need to be humanoid.

We need to start Waging Peace, as our ability to kill each other is outstripping our willingness to live peacefully together.


>What a time to be alive.

Totally. In a little while, you might even be able to marry a robot and even raise robot kids.

What a time to be alive indeed!

I highly doubt that that it will happen. But just mocking the celebration of paving a path towards the death of all things that makes being a human worth all the pain..


> the death of all things that makes being a human worth all the pain

I'd say that's the problem. There are people who think humans are uniquely special/purposed, and AI is systematically destroying that notion. They need to wake up, or they may find themselves jumping off a bridge or something.


Humans are special because they can feel. You know what it means to "feel", right?


Feelings are ultimately electrical patterns in the brain, just like everything else humans experience. And as such they can be manipulated and reproduced in any sufficiently capable brain-substrate. Only a matter of time before machines that can feel also become a thing, and then what's left?


>Feelings are ultimately electrical patterns in the brain

Correlation =/= causation.


There was nothing about causation here. Cause would be stimuli triggering memories, biased by the collective experience from past interactions and... DNA. Far more -ologies than I've studied involved.


No, what I meant is that just because we observe signals in the brain when we feel something, it does not mean that the "feeling" is caused by the signals.


> all things that makes being a human worth all the pain

Running fast or jumping high are what makes being a human worth all the pain?


Yknow, for a tech news aggregation website, some of you really hate technology


Do you think people on hackernews should embrace every use of technology?


Technology isn’t a single unified thing.

People can like GPS while disliking nuclear weapons without any contradiction.

I dislike the vast waste of resources happening during the current AI bubble, and don’t really care about generative AI.


Horses are faster than humans. I don't see them suddenly taking over based on that fact alone.


You can't "program" a horse to do construction or assembly line jobs, can you?


My contacts at various factories and my own eyes after touring said factories tell me that the assembly lines have been mostly run by programmed (no quotes required, just SPS) robots for the past 50 years or so. Welcome back to the 1970s I guess?

The ones I see deployed in construction do stuff like drilling holes in hard to reach places, or laying bricks. None of them look like people, though. Much like the typical household dishwasher hasn't been named Alice or Doris for the past 50+ years, but rather Bosch or Samsung and doesn't use actual hands.

But yeah, humanoid robots do look cool and many movies and books told us to be fearful of them.


From their perspective, it's training data that their competitors don't have. If they make it available, they fill in their moat.


They cannot scan the books then resell them or donate them under current US copyright law. It’s not clear to me that they could warehouse them if they wanted. In the recent Bartz v Anthropic case the judge ruled this destruction as legal, saying

> The print original was destroyed. One replaced the other.

So that there was still only one “copy” of the book. This is in compliance with the DMCA. You can make a personal digital copy of a work but then you cannot resell the hard copy and keep the digital one. Same principle applies here.


Nowhere in this description did it require destruction of the physical book. This is being done because it's easier to scan a shucked book, and this explanation is circulating because it's easier to blame it on the law and that pesky meddling government.


"Here, every purchased print copy was copied in order to save storage space and to enable searchability as a digital copy. The print original was destroyed. One replaced the other. And, there is no evidence that the new, digital copy was shown, shared, or sold outside the company. This use was even more clearly transformative than those in Texaco, Google, and Sony Betamax (where the number of copies went up by at least one), and, of course, more transformative than those uses rejected in Napster (where the number went up by “millions” of copies shared for free with others)."

"For the print library copies that Anthropic purchased and then converted into digital library copies, Anthropic already enjoyed entitlement to keep the copies in its library. The purpose of the copying was to keep them in its library but with more favorable storage and searchability properties. Copying the entire work was exactly what this purpose required. There was no surplus copying. The source copy was destroyed.

The third fair use factor favors fair use for the purchased library copies converted from print to digital."

Bartz v. Anthropic PBC, 787 F. Supp. 3d 1007 (N.D. Cal. 2025). https://docs.justia.com/cases/federal/district-courts/califo...


So if I scan a book, sell it, and keep using the scan, is that legal? (Spoiler: That's not legal. It's a violation of IP law.)


Selling it is not allowed. The inability to sell it does not require its destruction.


But copyright law does, because otherwise you have two copies.

This isn't theoretical, AI companies have finished lawsuits about this and this was the ruling.


The ruling was that what they did was within the law, not required by law in every detail. They cannot resell the copies. I saw nothing in that ruling that required their destruction, because it is not required.

A person can digitize their own books without destroying the original. So can Anthropic. They are choosing to destroy the books for easier scanning and trying to palm off the blame for it.


The ruling was that training is fair use but still they can't make unauthorised copies to enable training. They had to pay a huge fine for each unauthorised copy. So now they aren't making unauthorised copies.


Why would a company keep the hard-copy around at the risk of it being inadvertently given away, resold, etc.? It's a huge outstanding liability given that the illegal copying of works -- the other part of that case -- is what they settled out of court for some huge amount of money. Destruction is the only thing that makes sense.

I'm old enough to have been around when DCMA legislation was under discussion. Many people were dead-set against it and raised concerns over matters exactly like this. In Rainbows End (2006), Vernor Vinge wrote about a similar scenario where a robot went through the university library shredding books, and scanned the shredded pieces to recombined them into a digital archive.

Anthropic may be doing shady things and may have even done this on their own recognizance, we just don't know. As it stand, this is 100% a consequence of US copyright law, much of which was written by large corporations to protect their own assets.


I agree fully that it makes logistical sense. But it is not a legal requirement, and they should not be permitted to use that as an excuse to wash their hands of their own decisions.


I think I agree with you in spirit. I don’t like what these companies are doing, and Anthropic’s actions can for the most part stand on their own. Copyright law is just a special interest of mine, and I do think it’s important to recognize what external incentives exist and what they prioritize. Because other companies will act in similar manners under the same incentive structure, and the problem is going to cascade and magnify if it hasn’t already. There are active court rulings setting precedence for this behavior - take note!


Probably, if you sell it after the copyright expires.


Citation please? Bartz v Anthropic seems pretty clear, see also Authors Guild v Google and RIAA v Diamond Multimedia.


1 point by jonhohle 0 minutes ago | edit | delete [–]

You’re missing the point. It doesn’t require that they destroy the book, but it precludes them from giving it away. It’s their property, so they can choose to store it, but that has real, ongoing cost and may eventually leave unusable books anyway due to fire, pests, water damage, etc. if they’re not maintained properly.


I love how sci-fi authors like Ray Bradbury toyed around with a similar issue but then got it so wildly wrong.


More importantly: Once Anthropic is gone, all knowlege is lost.


It will probably be actioned off in the bankruptcy proceedings.


That’s an interesting angle. There’s probably some property value (though maybe not enough based on volume) to the books they purchased. I doubt there’s any value to the “backups” of those books. I’d imagine they’re normally transferable.


They cut the bindings off and feed loose leaf books through a document scanner. It would be difficult to store and probably unsellable, it's probably going in the trash.

To legally retain these scans, you must own the original book. You can sell or give away the original book (sans binding) but it's legally dubious as to whether the scan can be transferred along with it. So if Anthropic has no interest in storing thousands of loose leaf books, they are likely destroying both the original and scan as soon as possible.

At the end of the day, the only thing of value Anthropic has is the trained model which is definitely transferable.


It's already been distilled.


Wtf does this mean? “Their square display of olo occupied an angular width of 0.9°[1], around twice the diameter of the moon[7].”



Why would someone want to use a nested function, practically speaking?


Good C style is that every function that accepts a callback should also accept an opaque context pointer it then passes through unchanged to the callback. Usually the caller will allocate a structure on the stack or the heap, stash some of its local variables there, then use them in the callback. A nested function does the structure back-and-forth for you in the stack-allocated case. In GCC’s original formulation it also passes the context pointer implicitly

  size_t filter(bool (*predicate)(int), int *p, size_t n) {
      for (size_t r = 0, w = 0; r < n; r++) {
          if (predicate(p[r])) p[w++] = p[r];
      }
      return w;
  }
  size_t lowpass(int limit, int *p, size_t n) {
      bool lower(int value) {
          return value < limit; // use the parent's local variable
      }
      return filter(lower, p, n);
  }
but that requires an executable stack and TFA is about avoiding that part.


And if you want to write a templated data structure without actual templating or fancy macros, doing so with force-iined functions calling function pointers that are constant at the call site is a great way to do it. Unfortunately it's ugly and annoying to do this without nested functions :-/


For the non-capturing case: mainly to improve readability by allowing utility functions to be defined close to where they are used and with short names.

For the capturing case: to access context that is not available through global variables or function arguments, i.e., the same reason why closures are useful in other languages.

Here's an example, where I have a list of points that I want to sort based on distance to a chosen target point. I can use qsort() which takes an arbitrary comparison function, but has no way to provide context to that function beyond the input arguments:

    #include 
    #include 

    int main() {
        struct Point {
            int x, y;
        } points[3] = {
            { 3, 1 },
            { 2, 2 },
            { 5, 7 } };

        struct Point target = { 4, 5 };

        long dsq(const struct Point *p) {
            long dx = p->x - target.x, dy = p->y - target.y;
            return dx*dx + dy*dy;
        }

        int compare(const void *p, const void *q) {
            long a = dsq(p), b = dsq(q);
            return (a > b) - (a < b);
        }

        qsort(points, 3, sizeof(struct Point), compare);

        for (int i = 0; i < 3; ++i) {
            printf("%d,%d\n", points[i].x, points[i].y);
        }
    }
Note here that dsq() is a local function that accesses the `target` variable in the local function scope.

The usual workaround in standard C is to pass the necessary context as a function argument. That's why qsort_r() exists, which takes a context argument to be passed to compare(), but that's a non-standard GNU extension.

This practice of passing context pointers around is ubiquitous in C code, and it works, but it can get messy especially if you need access to multiple variables or variables from more than one nested scope. There is also a type safety issue: these context pointers are necessarily passed as void* which means they have to be cast back to the real type before use, which is where bugs can be introduced if the caller and receiver disagree on the actual type.


This is a good example. Without trampolines, this could look like this (Godbolt: https://godbolt.org/z/nK5fqMxjs).

    int main() {
        struct Point {
            int x, y;
        } points[3] = {
            { 3, 1 },
            { 2, 2 },
            { 5, 7 }
        };

        struct Point target = { 4, 5 };

        long dsq(const struct Point *p) {
            long dx = p->x - target.x, dy = p->y - target.y;
            return dx*dx + dy*dy;
        }

        typedef typeof(dsq) dsq_f;

        int compare(const void *p, const void *q, void *data) {
           wide(dsq_f) *dsq = data;
           long a = CALL(*dsq, (p)), b = CALL(*dsq, (q));
           return (a > b) - (a < b);
        }

        qsort_r(points, 3, sizeof(struct Point), compare, &CLOSURE(dsq_f, dsq));

        for (int i = 0; i < 3; ++i)
            printf("%d,%d\n", points[i].x, points[i].y);
    }
There are slightly different ways how to define the helper macros, I am still experimenting a bit. Here you could avoid the typedef if defined differently. But ideally, there would be native language support that avoids these macros.


Well, if you're already using qsort_r, what's the point of using nested functions, if you can have a context pointer with the target?

And if you're not using qsort_r, but reaching for _Thread_local, the target can be _Thread_local instead of dsq.


Fair. If you only have one object to access such as the target pointer, then it probably makes not much difference with void-pointer based APIs such as qsort_r (for new APIs it would add type safety). Where it removes more boilerplate code is when you have several such objects and would have to create an extra data structure to access them.


Or without qsort_r, you could use a thread local variable:

    typedef typeof(dsq) dsq_f;
    _Thread_local static wide(dsq_f) wdsq;
    wdsq = CLOSURE(dsq_f, dsq);
https://godbolt.org/z/3e157c6b1


When you want to use lambdas, but your language doesn't have lambdas, so you reach for the nearest thing instead.


Lambdas are just anonymous nested functions. But I like named nested functions more because they are more readable and would prefer them in most cases. Ideally you have both as most languages have.

I always wondered why C++ only added lambdas, but observing WG21 for a while, I assume this is just a random walk in language design. (not that it is different in WG14)


> Lambdas are just anonymous nested functions.

The important feature of lambdas is that they are expressions, not that they lack a name. The advantage of function expressions is you can write the body of the function exactly at the place where it is used. With GCC nested functions you either have to write the body of the function before its first use or else write the declaration of the function twice.

This matters for long chains of continuation passing:

  foo(arg1, arg2, [](){
          // do some work
          bar(arg3, arg4, [](){
                  // do some more work
                  baz(arg5, arg6, [](){
  
                  });
          });
  });
Compare to the following, where the control flow is all out of order:

  void cb(void){
          // Do some work
          void cb2(void){
                  // do some more work
                  void cb3(void){

                  }
                  baz(arg5, arg6, cb3);
          }
          bar(arg3, arg4, cb2);
  }
  foo(arg1, arg2, cb);


I agree with your point.

But I usually prefer the later anyway, because the code usually is not as nested anyway and having a name is often helpful, and also because I find the nested code with lambdas also not too readable. Other languages have better syntax for chaining functions in this way, i.e. with lambdas I would like to write like this:

  foo(arg1, arg2, _)
     .(int(int x)) { ... }
     .(int(int y)) { ... };
(edit: or something, I think I got it a bit wrong, but you get the idea)

But I agree, sometimes lambdas are better so it would be good to have both.

(There is the classical hack to define lambdas using statement expressions and nested functions.)


I can write numbers like three by just writing 3 in my code. When I want a named number I use a syntax like x = 3. Why should functions be any different? A language doesn't need different ways to name things for each type of thing. Integers, strings, functions etc: they can all use the same mechanism for naming.


Fair enough, But I am of the opinion that blocks of code and magic numbers should almost always be named, There is a lot of intent that is lost when the name is skipped.

It is also my main complaint about traditional math notation, They enjoy trying to make the notation as concise as possible, single letter symbols, embedded subparts, no names for anything. I understand that having super a tight concise notation is a massive benefit while in the flow state, thinking about the problem. But man it makes it rough for us casual math enjoyers coming in fresh to the topic.


I agree if your language is designed like this from the beginning as functional languages are, but in C you already have different syntax for functions. (edit: rephrased)


No exactly. "Lambdas" are usually function closures [1]. Which do not exist in C and were quite "late" in C++, because decent support of closures require automatic memory management (GC).

C++ lambda/closures are a bit clunky because you have to specify if the captures are by reference or by value, and you're better of having a good idea of what you're doing.

[1] https://en.wikipedia.org/wiki/Closure_(computer_programming)


GCC's nested functions can also capture variables by reference. A closure combines the function with the environment which is essentially what my wide pointer is that contains the static chain that points to the environment. But for full support of first-class functions you would want return functions even below the level of where the captured variables live which is not possible with GCC's nested functions because they are on the stack and then go out of scope. So yes, this would require moving them to the heap and generally GC. Which is why the attempts to put C++'s "lambdas" into C are problematic, because naively copied lambda design will work even less well in C compared to C++ where you at least have smart pointers.

If you are interested, I explore the design space here. https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3654.pdf


Lambda expressions in C++ are simply syntactic sugar for defining function objects (aka functors): structs that overload operator() so you can call them as functions. Once you realize this, their features and limitations become immediately clear.

For example, here is a typical use of a lambda expression to filter a vector of values:

    #include 
    #include 

    int main() {
        std::vector v = {3, 1, 4, 1, 5, 9, 2, 6, 5};

        int threshold = 5;
        std::erase_if(v, [&](int i) { return i < threshold; });

        // prints 5 9 6 5
        for (int i : v) std::cout << i << '\n';
    }

The lambda expression is essentially shorthand for:

        ...
        int threshold = 5;
        struct lambda_t {
            int &threshold;
            bool operator()(int i) {
                return i < threshold;
            }
        };
        std::erase_if(v, lambda_t{threshold});
        ...
You could always do this in C++. The added value of the lambda expression syntax is that the compiler generates the boilerplate, and generates a unique name for lambda_t.

The important takeaway is that every lambda expression corresponds with a unique type that is _not_ a function type, but a class type. Consequently, lambda expressions can only be passed to template functions like std::erase_if, which are parameterized with the callback type.

You cannot pass a lambda expression to a function that expects a function pointer (e.g. bool(*)(int) in this example), and that's where they differ from GCC-style nested functions, which actually behave like functions. It also explains why lambda expressions don't need a trampoline.

As an aside, you _can_ pass lambdas to non-generic functions using a type-erasing wrapper like std::function, but std::function is itself a class type too, so that still doesn't allow you to convert it to a plain function pointer.

Finally, you can of course assign a name to a lambda expression value, using this common pattern:

    auto greet = [](const char *name) { std::cout << "Hello " << name << "!\n"; }
    greet("Alice");
    greet("Bob");
(Note that `auto` is necessary here because there is no way to explicitly refer to the compiler-generated name for the lambda type.)

This is the closest you can get to a local function definition in C++. Admittedly the syntax is a little odd. You might wonder why there wasn't some additional syntactic sugar to make the definition look more normal. I suspect that wasn't a random decision, but rather intentionally avoiding conflicts with existing language extensions like GCC's local function syntax.


> lambda expressions can only be passed to template functions

> there is no way to explicitly refer to the compiler-generated name for the lambda type.

"Voldemort" types. While intellectually I get the explanation for why C++/Rust lambdas are like this, I still strongly dislike them. Occasionally being unable to even articulate what something is feels like a failure in language design.

C recently got type inference via the "auto" keyword and it seemed like almost immediately there was a proposal to add voldemort types to the language.


I know it's not the same, but you can "kind of" name them by using them as a template parameter, then, scoped to the template, you can reference them under the template parameter name.

Anyway, I don't see it mentioned anywhere in this discussion, but imo the area where c++ lambdas shine is the way they interact with copy constructors and move constructors.


>You cannot pass a lambda expression to a function that expects a function pointer (e.g. bool(*)(int) in this example)

To be pedantic, you can: as long as the lambda doesn't close over any local variable, the object will decay to a function pointer.


Regarding function syntax in C++: GCC's C++ frontend does not support nested functions. But more importantly, even if it did, I do not think there would be any conflict at all. While lambdas are lowered to function objects with an unique anonymous type in C++, the semantics of a lambda that uses lvalue capture

  auto f = [&](int x) - > int { return x + z; };
is the same as GCC's nested function

  int f(int x) { return x + z; }
except that latter can be converted via a trampoline to a regular function pointer (and maybe the observable type). But you could do just the same with a lambda using a trampoline! In any case, there is no conflict, either this conversion is allowed and one needs some hack to make it work such as a trampoline or it is not.

So in C++ you could simply lower such nested functions to lambdas and it would cause no confusion with GCC's nested functions at all, because from a user's point of view they would work identically.


C++ bundles together a way to write functions inline in an expression (what I’d call “lambdas” in general) and a way to create closures with strictly nested lifetimes, but there’s no law of nature tying the two together. Even in C++ the essentially separate declaration “auto f = [&](... blah ...) { ... 50 lines of code ... };” is pretty common. (And of course GCC’s nested functions predate C++11 by twenty years.)


Say to strictly enforce modularity, e.g helper functions that can only be accessed within its function.

Pascal supports it (at least Turbo Pascal, no idea about ISO Pascal).


For a counterpoint, see David R. Hanson's "Is block structure necessary?" (1981) [0] — back in those days, "block structure" meant nested routines with nested scopes — which argues that having instead a proper module system, with explicit control over what's being exported from a module, not only gives a better modularity, decomposition, and encapsulation, but also simplifies both the language's implementation, and the run-time structures it needs (remember displays, and the hardware support for them e.g. x86's ENTER?).

    Block structure is traditionally considered an a priori requirement for algorithmic program-
    ming languages. Most new languages since Algol-60 have block structure. Reasons exist,
    however, to omit the general form of block structure — nested procedure definitions in which
    references to identifiers defined in outer procedures are permitted — from programming
    languages, especially those intended for systems programming applications. This paper
    reviews the concept of block structure and considers its advantages and disadvantages. It
    concludes that, in many cases, a module facility is superior to block structure and should be
    considered in lieu of block structure in future languages.
[0] https://drh.github.io/documents/blockstructure.pdf


The traditional way of doing this in C is simply static functions. Every .c file has exactly one non-static function and all the other helper functions are static.


RAII style cleanup e.g. no gotos


Just a little cleaner than placing it in the global or file namespaces.


So that you can name a section of code without polluting the namespace.


I use them all the time. It's one of the nicest and cleanest features of D. It's an elegant way of:

1. grouping together strongly related functions that are implicitly private to the enclosing function

2. obviating the need to create a struct in order to pass common context to multiple functions

For an example, here's a tree walking function that uses a nested function for the recursion:

    private void unrollWalker(elem* e, uint defnum, Symbol* v, targ_llong increment, int unrolls) nothrow
    {
        int state = 0;

        /***********************************
         * Walk e in execution order, fixing it according to state.
         * state == 0..unrolls-1: when eincrement is found, remove it, advance to next state
         * state == 1..unrolls-1: replacing instances of v with v+(state*increment),
         * state == unrolls-1: leave eincrement alone, advance to next state
         * state == unrolls: done
         */

        void walker(elem* e) @trusted
        {
            assert(e);
            const op = e.Eoper;
            if (ERTOL(e))
            {
                if (e.Edef != defnum)
                {
                    walker(e.E2); // this function is @trusted because of this union access
                    walker(e.E1);
                }
            }
            else if (OTbinary(op))
            {
                if (e.Edef != defnum)
                {
                    walker(e.E1);
                    walker(e.E2);
                }
            }
            else if (OTunary(op))
            {
                assert(e.Edef != defnum);
                walker(e.E1);
            }
            else if (op == OPvar &&
                     state &&
                     e.Vsym == v)
            {
                // overwrite e with (v+increment)
                elem* e1 = el_calloc();
                el_copy(e1,e);
                e.Eoper = OPadd;
                e.E1 = e1;
                e.E2 = el_long(e.Ety, increment * state);
            }
            if (OTdef(op) && e.Edef == defnum)
            {
                // found the increment elem; neuter all but the last one
                if (state + 1 < unrolls)
                {
                    el_free(e.E1);
                    el_free(e.E2);
                    e.Eoper = OPconst;
                    e.Vllong = 0;
                }
                ++state;
            }
        }

        walker(e);
        assert(state == unrolls);
    }
Only one argument needs to be passed to walker(), because the other context data is accessible from the enclosing function.

https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ba...


Encapsulation


Guidelines | FAQ | Lists | API | Security | DMCA | Apply to YC | Contact

Search: