in reply to Re^4: Out of memory.
in thread Out of memory.

It wasn't in a void context. It was a scalar context :)

That said, I'm still in two minds as to whether the 'map in a void context' problem is still a problem any more as (I believe) the main practical reason for not doing it was the inefficiency caused by building the return list only for it to be discarded. Since map now tests for context and doesn't bother building the list if in a void context, the reasons now seem esoteric/style related rather than practical. I agree that in most cases a for loop or modifier is better, but if you need to use a second modifier, map lends itself to the purpose. I wouldn't use it often, but I'm still undecided whether a blanket ban is called for.

As for the File::Find and related calls. I have a (probably irrational) phobia about them, and it's not only to do with performance. I dislike their callback method of working, and their reliance upon global vars amongst other things. For example, the anonymous sub in your example is being called (many times) in a void context and the (unavoidable) return value is being discarded. How is this different from calling map in a void context?

This really is "language lawyer" type stuff, but I seriously would appreciate your reaction/interpretation as I know you have made a point of studying many issues of this type.

I'd also like to understand your (though that's not as bad on Win32) comment. How/why is this different for Win32 as compared to other OS's? I've racked my brains to see what you mean, but the significance escapes me?


Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller

Replies are listed 'Best First'.
Re^6: Out of memory.
by Aristotle (Chancellor) on Jul 23, 2003 at 19:04 UTC
    if you need to use a second modifier, map lends itself to the purpose.
    Hm? It takes a block, doesn't it? Not really comparable to a modifier.
    How is this different from calling map in a void context?

    Good question. Although if you go down that route, you could also say I'm calling find in void context, and the same about pretty much any prodedure call and basically every other line of code.

    In my point of view it's more of a conceptual question - the memory and performance concerns are additional, not the sole reason. I guess this is the mathematical part of my brain kicking in here - but to me, map is for mapping one set to another, and the fact that to do so it loops over the input is more of an implementation detail. On a dataflow architecture, as opposed to the Neumann machines Perl runs on, you could actually do the entire processing in large chunks at once.

    Ivory tower? You decide. (After all, my weakness is false hubris, as opposed to the false laziness most people have to overcome.)

    How/why is this different for Win32 as compared to other OS's?
    Traversal is easier to get right on Win32 systems. Besides some red herring special file types supported by more recent NTFS variants (which, to my knowledge, can be treated as plain files for most intents and purposes, anyway), there are only regular files and directories in a Win32 file system. On Unixoid systems, the situation is decidedly more complex with symlinks in the traversal equation. In fact it's even more tricky if you're collecting statistics on files, considering you have hardlinks, sparse files, fifos, device nodes, and possibly other more exotic beasts to deal with.

    Makeshifts last the longest.

      Sorry for the clumsy description. I was trying to say that if want to do

      some_statement for some_range while some_condition;
      which is perfectly legal and very useful syntax in a couple of languages I have used--including various DEC Basics which I think is where the modifier forms of if, for while & until were borrowed from-- but illegal in perl, then using
      map{ some_statement } some_range while some_condition;

      is a useful substitute.

      I take your point about map being conceptually different from a loop though, and I do try to avoid misusing it most of the time.

      Thanks for the explaination on the traversal thing. I always forget about the special file types. I can see how that routine could disappear up it's own er...stack if it encountered a circular symlink.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller

        map{ some_statement } some_range while some_condition;
        You have a block there :), and the keyword goes in front too - might just as well do
        do { some_statement for some_range } while some_condition;

        At least, that's me.

        As far as the symlink is concerned, it's as easy as ln -s . foo (for which there actually are legitimate uses every once in a blue moon - I've used it). There are also a million other scenarious that require to decide on an individual basis whether a symlink is to be followed or not.

        Another thing I just remembered is AFS (Andrew File System) - a hugely useful truly distributed filesystem, which, to work as it does, has the unfortunate consequence that even absolute paths can mean different things under different conditions.

        If you fiddle long enough, you can come up with some pretty far out pathological cases on Unix. File::Find will handle them correctly - modulo what few bugs may be left, of course, but that's the advantage of having code reused and retested millions of times.

        Makeshifts last the longest.