I'm not sure I follow -- I don't think the Erlang folks are suggesting that people upgrade some things and not others. Is your concern just that the upgrade from one tagged state to the next isn't atomic?
Re:Full-time Erlang programmer gives his view :]
on
Programming Erlang
·
· Score: 1
lists:foreach, in conjunction with lists:seq, seemed like enough to cover most (though not all) typical "for" cases. I suppose in some cases (like iteration over a large range of integers), it'd still be desirable to write your own combinator, e.g. something like:
Either way, it shouldn't be necessary to use explicit recursion in the main portion of your code, and very seldom will explicit recursion be the clearest way. Would you be willing to paste an example of the kind of structure you were having trouble with? I can either help you out or be proven wrong by example.:)
Argh, I misplaced the parenthesis in the Haskell version. Should have been:
result = map (\item -> f (g item)) source
Or, more idiomatically:
result = map (\item -> f $ g item) source
Re:Full-time Erlang programmer gives his view :]
on
Programming Erlang
·
· Score: 1
Well, ideally it wouldn't have global variables either.:)
What sort of uses of "for" did you have in mind, though? Erlang provides lists:foreach and lists:map in the standard library, which covers many typical uses of "for" in other languages.
Re:Full-time Erlang programmer gives his view :]
on
Programming Erlang
·
· Score: 1
Ah, actually they do provide. Just takes a little digging in the standard library that I guess most people don't do.
Re:Full-time Erlang programmer gives his view :]
on
Programming Erlang
·
· Score: 1
Ideally, in functional programming you want to use neither loops nor explicit recursion for iteration, but combinators instead. I've seen a lot of Erlang programs unnecessarily using explicit recursion, though. They ought to have provided a standard looping/iteration combinator (besides map) in the standard library, but there's nothing preventing you from writing one for yourself (using recursion) and using that everywhere rather than trying to work with explicit recursion everywhere.
Yes, that's a reasonably good way to think of them, with the proviso that an Erlang process doesn't bind particular code to the receipt of particular messages like you see in OOP (where particular bodies are bound to particular methods). When an Erlang process receives a message, it's up to the process to decide what to do with it.
The difference between functional and logic programming is that the former's model of evaluation is function application/beta-reduction, whereas the latter's is unification. It isn't just a syntactic distinction.
Egh, part of the problem is that the functional programming example is pretty crappy, and they're both done in Python, which does not lend itself to readable functional programs. If the language doesn't already provide function composition, it's more sensible to write it out in a case like this. Showing the evolution between the two might also have been helpful.
Reformulating in Ruby (a more neutral language), we get:
result = []
for item in source
temp = g(item)
temp2 = f(temp)
result << temp2
end
Which is like (lambda declares a function in-place, and 'each' applies a function to each element in a collection in turn):
result = []
source.each(&lambda { |item|
temp = g(item)
temp2 = f(temp)
result << temp2
})
Which, in Ruby, can be more concisely written:
result = []
source.each { |item|
temp = g(item)
temp2 = f(temp)
result << temp2
}
Which can be condensed to:
result = []
source.each { |item| result << f(g(item)) }
Which you don't need to write out because it turns out there's already a standard functional way to do this, where the collection-building is handled internally:
result = source.map { |item| f(g(item)) }
At this point we need to switch languages to get more "functional" without verbosity, so I'll rewrite that in Haskell:
result = map (\item -> f(g(item))) source
Now, that anonymous function we've been using is no longer necessary, because there is a way to directly combine f and g into a single function that has the effect of both (the . operator is the equivalent of the grotty compose2 in the python example):
result = map (f . g) source
So, we get a very concise translation of "The result is the source list with g and f applied to each element". We know what map does (build one list from another by applying a function to each element), and we know what . does (combines two functions). Much less boilerplate, and much less to debug or mistype. Compared to imperative programming, you can more often build simple solutions out of well-tested library routines, rather than rewriting essentially the same list-building loop for the thousandth time and having to check/debug it each time.
Now, I won't lie to you: functional programs are only concise like this if you can find the right abstraction to use, which is harder for some problems than for others, and requires a different set of skills than imperative programming. However, I know firsthand that developing those skills can be very rewarding and will improve the quality and concision of one's programming in any paradigm.
Well, it's not as if the article was Slashdotted at the time.:) I think it's fair to gripe about hand-waving dismissals if their rebuttal is already in the very article being dismissed.
The trouble with setting the kernel ABI in stone is that it would prevent a lot of the refactoring which is a normal part of the Linux development process. Even the vendors who have stable kernel ABIs (and much slower development processes) tend to roll them periodically for that reason.
I think this reflects a trend that we're seeing more of lately: technology using materials and processes taken from biology. This shouldn't be too surprising, as biology is optimized for the particular physics and chemistry of our universe.
You're assuming that physics requires the universe to have a Euclidean geometry, which isn't the case anymore. Given that, whether we could tell the difference between an topologically open and a topologically closed universe by observing things "meeting" from opposite directions depends on how large the space in question was, and if it is expanding. If it's expanding faster than something could make it from one side to the other in the age of the universe, we couldn't. And that may be the case with our observable universe...
For those who believe in a heaven/hell, perhaps a hole in the universe is how one would get there? I have no idea what theological/philosophical types would say to something like that.
Since Heaven and Hell are states of being, not places, a physical "portal" seems unnecessary at best.
That said, this hole isn't even a hole in the universe, just a mind-bogglingly large gap in the matter that sparsely fills it.
No, that isn't what the Big Bang theory claims at all. The Big Bang didn't happen in existing space; rather, spacetime itself expanded from that singularity. Matter, once it formed, mostly stayed where it was, clumping a little but generally becoming uniformly less dense as the spacetime it's embedded in expanded.
The weird thing here is that the void is on a much larger scale than any clumping we've observed: for some reason either matter inexplicably didn't form there, or something happened to it on a cosmically unimaginable scale. The matter didn't simply get pushed around, or moved towards the edges by non-uniform spacetime expansion, or we'd see increased density near the edges of the void (which we don't).
It's simply that the CMB photons get a slight blue-shifty boost when interacting with matter.
There's not much matter in the void, though, so photons that came through it look slightly cooler/more redshifted than ones that didn't (and had more opportunities to interact with matter along the way).
I haven't tried it but I am sure you could hack together a solution by combining qemu and nspluginwrapper.
That's... how you say... unlikely to run at a usable speed, particularly on my G3. Also it'd mean maintaining an entire VM instance just for the plugin, with the associated memory and disk overhead.
Frankly, that theory about Google's DRM plan is just dumb. But your strings-attached metaphor for DRM is very good! (One of the best I've heard, in fact.)
Of course it doesn't work in-process. Can't mix 32-bit shared libraries with 64-bit executables. But 32-bit flash does work out-of-process with nspluginwrapper, which works with 64-bit Firefox.
In this case, it's a simple matter of giving preferential (or anti-preferential) treatment to traffic from particular IP ranges based on what their owners are willing to pay.
I'm not sure I follow -- I don't think the Erlang folks are suggesting that people upgrade some things and not others. Is your concern just that the upgrade from one tagged state to the next isn't atomic?
lists:foreach, in conjunction with lists:seq, seemed like enough to cover most (though not all) typical "for" cases. I suppose in some cases (like iteration over a large range of integers), it'd still be desirable to write your own combinator, e.g. something like:
:)
forseq(Fun, Start, Limit) when Start < Limit ->
Fun(Start),
forseq(Fun, Start + 1, Limit);
forseq(_, _, _) -> {}.
Either way, it shouldn't be necessary to use explicit recursion in the main portion of your code, and very seldom will explicit recursion be the clearest way. Would you be willing to paste an example of the kind of structure you were having trouble with? I can either help you out or be proven wrong by example.
Argh, I misplaced the parenthesis in the Haskell version. Should have been:
result = map (\item -> f (g item)) source
Or, more idiomatically:
result = map (\item -> f $ g item) source
Well, ideally it wouldn't have global variables either. :)
What sort of uses of "for" did you have in mind, though? Erlang provides lists:foreach and lists:map in the standard library, which covers many typical uses of "for" in other languages.
Ah, actually they do provide. Just takes a little digging in the standard library that I guess most people don't do.
Ideally, in functional programming you want to use neither loops nor explicit recursion for iteration, but combinators instead. I've seen a lot of Erlang programs unnecessarily using explicit recursion, though. They ought to have provided a standard looping/iteration combinator (besides map) in the standard library, but there's nothing preventing you from writing one for yourself (using recursion) and using that everywhere rather than trying to work with explicit recursion everywhere.
Yes, that's a reasonably good way to think of them, with the proviso that an Erlang process doesn't bind particular code to the receipt of particular messages like you see in OOP (where particular bodies are bound to particular methods). When an Erlang process receives a message, it's up to the process to decide what to do with it.
The difference between functional and logic programming is that the former's model of evaluation is function application/beta-reduction, whereas the latter's is unification. It isn't just a syntactic distinction.
Egh, part of the problem is that the functional programming example is pretty crappy, and they're both done in Python, which does not lend itself to readable functional programs. If the language doesn't already provide function composition, it's more sensible to write it out in a case like this. Showing the evolution between the two might also have been helpful.
Reformulating in Ruby (a more neutral language), we get:
result = []
for item in source
temp = g(item)
temp2 = f(temp)
result << temp2
end
Which is like (lambda declares a function in-place, and 'each' applies a function to each element in a collection in turn):
result = []
source.each(&lambda { |item|
temp = g(item)
temp2 = f(temp)
result << temp2
})
Which, in Ruby, can be more concisely written:
result = []
source.each { |item|
temp = g(item)
temp2 = f(temp)
result << temp2
}
Which can be condensed to:
result = []
source.each { |item| result << f(g(item)) }
Which you don't need to write out because it turns out there's already a standard functional way to do this, where the collection-building is handled internally:
result = source.map { |item| f(g(item)) }
At this point we need to switch languages to get more "functional" without verbosity, so I'll rewrite that in Haskell:
result = map (\item -> f(g(item))) source
Now, that anonymous function we've been using is no longer necessary, because there is a way to directly combine f and g into a single function that has the effect of both (the . operator is the equivalent of the grotty compose2 in the python example):
result = map (f . g) source
So, we get a very concise translation of "The result is the source list with g and f applied to each element". We know what map does (build one list from another by applying a function to each element), and we know what . does (combines two functions). Much less boilerplate, and much less to debug or mistype. Compared to imperative programming, you can more often build simple solutions out of well-tested library routines, rather than rewriting essentially the same list-building loop for the thousandth time and having to check/debug it each time.
Now, I won't lie to you: functional programs are only concise like this if you can find the right abstraction to use, which is harder for some problems than for others, and requires a different set of skills than imperative programming. However, I know firsthand that developing those skills can be very rewarding and will improve the quality and concision of one's programming in any paradigm.
The second one doesn't require particularly deep thought to understand, but it does require a very different way of thinking about code.
Erlang is a functional language with prolog-style unification for pattern matching, just like one sees in ML or Haskell.
Well, it's not as if the article was Slashdotted at the time. :) I think it's fair to gripe about hand-waving dismissals if their rebuttal is already in the very article being dismissed.
The trouble with setting the kernel ABI in stone is that it would prevent a lot of the refactoring which is a normal part of the Linux development process. Even the vendors who have stable kernel ABIs (and much slower development processes) tend to roll them periodically for that reason.
I've found that a rule-based IP firewall like netfilter works well.
You know something's wrong when you're talking about driving people to use software rather than attracting them to it.
I think this reflects a trend that we're seeing more of lately: technology using materials and processes taken from biology. This shouldn't be too surprising, as biology is optimized for the particular physics and chemistry of our universe.
You're assuming that physics requires the universe to have a Euclidean geometry, which isn't the case anymore. Given that, whether we could tell the difference between an topologically open and a topologically closed universe by observing things "meeting" from opposite directions depends on how large the space in question was, and if it is expanding. If it's expanding faster than something could make it from one side to the other in the age of the universe, we couldn't. And that may be the case with our observable universe...
Since Heaven and Hell are states of being, not places, a physical "portal" seems unnecessary at best.
That said, this hole isn't even a hole in the universe, just a mind-bogglingly large gap in the matter that sparsely fills it.
No, that isn't what the Big Bang theory claims at all. The Big Bang didn't happen in existing space; rather, spacetime itself expanded from that singularity. Matter, once it formed, mostly stayed where it was, clumping a little but generally becoming uniformly less dense as the spacetime it's embedded in expanded.
The weird thing here is that the void is on a much larger scale than any clumping we've observed: for some reason either matter inexplicably didn't form there, or something happened to it on a cosmically unimaginable scale. The matter didn't simply get pushed around, or moved towards the edges by non-uniform spacetime expansion, or we'd see increased density near the edges of the void (which we don't).
It's simply that the CMB photons get a slight blue-shifty boost when interacting with matter.
There's not much matter in the void, though, so photons that came through it look slightly cooler/more redshifted than ones that didn't (and had more opportunities to interact with matter along the way).
That's ... how you say ... unlikely to run at a usable speed, particularly on my G3. Also it'd mean maintaining an entire VM instance just for the plugin, with the associated memory and disk overhead.
Frankly, that theory about Google's DRM plan is just dumb. But your strings-attached metaphor for DRM is very good! (One of the best I've heard, in fact.)
It's an idiom; just as "couldn't care less" and "could care less" are synonymous.
Of course it doesn't work in-process. Can't mix 32-bit shared libraries with 64-bit executables. But 32-bit flash does work out-of-process with nspluginwrapper, which works with 64-bit Firefox.
:(
Still no love for us PPC users though
In this case, it's a simple matter of giving preferential (or anti-preferential) treatment to traffic from particular IP ranges based on what their owners are willing to pay.