![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible wrote:
> On 09/03/2011 06:22 PM, Darren New wrote:
>> Having worked with Erlang, here's some comments.
>
> In what capacity are you "working with Erlang"?
I'm not, currently.
> While I doubt anyone actually *wants* unreliable software, there can't
> be too many problems that require distributed programming.
Unless you want to listen to radio stations in several different cities and
integrate the results. Altho I wound up writing my own stuff for that and
not using Erlang, that was the experiment.
> Erlang is partially functional, in that functions are apparently
> first-class, and it's got single-assignment and immutable data
> structures.
Functions in C are first class. That doesn't mean it's functional. The
immutable data structures come from the single-assignment, except where the
data structures aren't immutable, of which there are several.
> On the other hand, it doesn't enforce referential
> transparency; you can put side-effects anywhere you like.
Well, that's the killer. To me, if every statement can have side-effects,
then it's not a functional language. It's just single-assignment. You have
none of the benefits and all of the draw-backs of a functional language in
Erlang.
> The document I
> read claims that it's considered beneficial to limit side-effects to
> just a few places in the codebase,
Except that message sending and message receiving are both side-effects as
is spawning or linking another process, so that works pretty poorly. Plus,
as I said, having the side-effects means you cannot (for example) use your
own functions in guards. Essentially, nothing is actually functional in the
language *except* assignment and a handful of built-ins. (Not even all the
built-ins, for that matter.)
> the language itself doesn't /enforce/ any kind of strong separation
> between pure and impure code.
For some reason, the Erlang enthusiasts think the crappy syntax and the
single-assignment procedures are intentional and beneficial properties of
the language. Like any niche language, the fanboi's refuse to accept that
any compromise was made during its design.
>> If it was *actually* functional, you could put your own functions in
>> guards, for example.
>
> Wait - you *can't* do this already?? o_O
> Why on earth would you design it this way?
Because your own functions aren't referentially transparent, because the
language isn't actually functional, even at that level. The functions in a
guard are the ones that *are* functional. Not even all the built-in
functions can go in guards.
Actually, in the documentation, I think there's a note on each built in
function that says whether you can use it in a guard or not.
>>> - The system is supposedly insanely reliable. People toss around "nine
>>> 9s up-time" as if this is some sort of experimentally verified *fact*.
>>
>> It is. They've been running a commercial switching network with it for
>> something like 10 years, and one of the six data centers lost power or
>> something and all the machines in it for 20 minutes once, so they had a
>> 15% downtime for 20 minutes out of ten years.
>
> One data point is scientific fact?
It's a scientific fact that you can achieve nine 9's of uptime over the
course of a decade with programs written in Erlang, yes. Pretty sure that's
really, really hard to do with any other programming language.
> (Presumably both processes have to be running within the same logical
> "node", but then again also presumably you wouldn't have more than one
> node on the same box except for test purposes anyway...)
You start up the run-time with a command-line argument that says "Hey, I'm a
node in a distributed program". Wings3D doesn't do this, so it's not a node.
> As I say, this doesn't really seem to be spelled out anywhere else that
> I could find, and it seems a rather crucial detail.
It's kind of in all the books and stuff. I think the PhD thesis is presumed
required reading, if nothing else.
>>> less the same kinds of error handling that any other language provides
>>> - catch/throw, etc.
>>
>> Huh. I didn't even know it provided catch/throw. I've never seen that
>> used, actually.
>
> Yeah they do. It's in there. Apparently the catch functions turn an
> exception into a tuple begining with 'EXIT' and followed by some stuff.
> Using throw you can make catch return an arbitrary data structure.
Ah, I see. Yes, I had forgotten about that.
> (Quite how you tell the difference between an exception and a normal
> result is left to the imagination...
Well, an exception will start with EXIT, while a regular result is unlikely
to, unless you specifically confuse things that way.
> It looks like you can use throw to
> make it look like the catch block exited normally.)
Yes. Basically, it lets you return early.
> Right. So it just sends heartbeat messages? (I presume the bit about
> rebooting the machine is optional; you wouldn't want your PC to reboot
> just because Wings 3D crashed, for example.)
Yes, it's a separate monitor process. It sends heartbeats as well as watches
for a couple other simple things.
>>> Message sending has the curious property that message delivery is
>>> /not/ guaranteed, but message ordering /is/ guaranteed. Like, WTF?
>>
>> Message delivery isn't guaranteed because it's asynchronous, and the
>> remote machine may crash between the time you send the message and the
>> time the remote machine receives it. Ordering *is* guaranteed because if
>> the remote machine crashes before it gets message #5, it won't get
>> message #6 either.
>
> You mean that if message #5 doesn't arrive, message #6 is actually
> guaranteed not to arrive?
If message #5 didn't arrive because the receiving machine crashed, yes,
message #6 isn't going to be received either. If message #5 didn't arrive
because the network switch died, then #6 isn't going to be delivered either.
> TCP guarantees both delivery and ordering. Unless the connection
> actually breaks. So is that all Erlang is saying? That it if one of the
> machines catches fire, Erlang can't guarantee that messages will be
> delivered to it?
Yes, exactly. More precisely, you can't tell if the message was received
and processed or not.
> These people are /serious/ about reliability. o_O
Well, yes, that's how you get 5 minutes of downtime over the course of 10 years.
>> Knowing the receiver got the message is as simple as adding code to send
>> an ack each time you handle a message.
>
> Network protocols 101: It's not that simple. It is possible for the
> message to arrive, but the acknowledgement itself to fail to be delivered.
If the ack fails to be delivered, it's because the receiving machine (nee
sender) has crashed and hence doesn't need to see the ack.
Well, not quite. If the network between the machines dies, each machine is
going to think the other crashed. This makes a mess. Mnesia has all kinds of
crap in place to recover from this, especially given that you might make
independent updates to the same table in two places.
> Now, if you're running on TCP, so that ordering and delivery are
> guaranteed (unless there's no transport or no endpoint), the only way
> this can happen is if the transport or the endpoint dies after the
> message is received, which is probably just as bad as the message not
> being delivered...
Right. The point of their warning is, you have to deal with messages not
making it one direction or the other. You don't have to deal with the
messages being out of order. You have to deal with the fact that if you tell
a remote machine to do something, it might not happen. You don't have to
deal with the fact that if you tell a remote machine to do two things, it
might do them in a different order.
> Thing is, I can open the REPL and type in a function, and then ask to
> spawn that on a remote node. How does *that* work?!
Hmmm. Actually, I think perhaps it *is* willing to ship functions around.
The details escape me at the moment. Maybe you can send functions but not
modules? I don't honestly remember.
> I'll bet. No doubt somebody has written libraries for other languages to
> speak the same wire protocol.
I don't know. Probably, but I'm not sure why you would.
> I notice that connecting one Erlang node to another causes the two nodes
> to connect to *all* the nodes that each endpoint knows about.
Yes, unless you tell it not to.
> I'm not actually sure why though.
Reliability. ;-)
> You would think that a fully interconnected
> mesh would quickly exhaust the supply of TCP ports too.
Unless you have more than 50,000 machines, unlikely.
>>> In other words, you're authorised if you can
>>> actually access the system in the first place.
>>
>> Yes, exactly.
>
> Ouch.
One of the OTP functions shows how to authenticate and encrypt the
connection en Erlang code, IIRC. That's also one of the tutorials.
Imagine a room full of a few thousand processors. One outgoing internet
connection running thru a firewall that's happy to VPN anything going out to
a known location, and which drops anything going in or out from an unknown
IP. Why encrypt everything?
Actually, I had forgotten. There is a "cookie" you can set, and anyone
connecting needs the same "cookie". So there is a minimal security level,
not unlike the similar feature in X servers.
> You say "sure", but the documentation sings about how reliable Erlang is
> and makes it sound like all this stuff just happens by magic, because
> Erlang is so wonderful. The truth is actually that Erlang just
> implements the minimal features required to let _you_ build complex,
> robust, distributed applications.
What, you're believing fanboi's?
If you want the version that actually *does* magically distribute and make
reliable your code, you want to read about Hermes, a language designed by Strom.
>> The two-versions limit is because the code itself isn't GCed. They
>> document that they could have GCed the code, but that would have added
>> lots of overhead for something relatively rare.
>
> Fair enough.
Plus, you should be dealing with the occasional "process suddenly ends for
no reason" exception robustly anyway. :-)
> You'd have to be able to do a lot of things. It would require careful
> application design, but it doesn't look especially difficult. (To get
> the framework done, anyway. Making the application itself sounds really
> hard, in Java or Erlang.)
Heck. Honestly, you can do it in Ada. Ada has facilities for declaring some
library code as capable of being hot loaded and unloaded.
> I don't mind which level the assistance is implemented at, just so long
> as there *is* some. ;-)
I found it annoying that there's no global roadmap. So you read about
something and it says "If X happens, a message is sent to the error logger."
WTF is the error logger? Where's the documentation. Then you track that
down, and it's all talking about bits and pieces that are also not
documented, etc, with the assumption that you have a bunch of people who
wrote the error logger hanging around to tell you how to find where the
errors got logged and such.
>> Realize that most of these "systems" you're talking about are actually
>> implemented as Erlang code.
>
> Hey, it worked for Smalltalk. ;-)
Yeah, basically the same idea, except instead of an "image" you actually
have a bunch of running processes.
>> I agree about the syntax etc. It's quite possible a better type system
>> would make it easier.
>
> Escaped experiment, eh? ;-)
That's exactly what it was. Except that by the time it escaped, there were
millions of lines of production code written in it, so you couldn't even
reasonably fix it.
>> You should also check out Hermes, which is essentially the same thing
>> with an astoundingly strict and high-level type system.
>
> Heh, there is never enough free time. ;-)
I don't think the book is available any more, either. I should scan mine.
> The advice presumably being that workers should only receive "real"
> messages, and supervisors should only receive exceptions. Then there can
> be no ambiguity. (Until the supervisor's supervisor asks it to do
> something...)
Well, more like, normal worker processes shouldn't communicate with messages
that start with the atom "EXIT". It's not that hard. It's like saying "don't
make closing the TCP connection the confirmation." There's only one or two
patterns that the error messages use. You shouldn't use "Close" as the name
of the routine to invoke when you want your object to keep running, either.
> Actually, that's a point. Each process has *one* mailbox. Not one
> mailbox for each process it's communicating with. Just *one*. So you
> have to manually figure out who each message came from - usually by
> having the sender put a reply address in manually.
Yep.
Hermes gives you as many mailboxes as you want, with as many connections to
each mailbox as you want, and you can send both connections and mailboxes in
messages to other processes. So if you want hot-swap code, write your
processes as being capable of packaging up its mailboxes and sending them to
a new process.
> So you're saying that all the "interesting" stuff like the SSL
> implementation is actually just an off-the-shelf C library?
It's possible.
> I never did understand what's so great about Tk. It looks horrid, it's
> really hard to use, and it's almost impossible to get the layout you
> want...
Well, no, it's really easy to use, it's easy to get a good-looking layout,
and it only looks horrid because it looked cutting-edge 10 years ago and
nobody ever improved the look of it since then. (Altho they've worked on
that more lately.)
That's exactly why half a dozen non-Tcl languages actually went so far as to
embed a Tcl interpreter into their code in order to be able to use Tk. I'm
pretty sure it's not Tk that's at fault here. ;-)
>> In general, network switching isn't that hard real-time, because you
>> usually have custom hardware to do the switching. A 5ESS (which can
>> handle up to 800,000 phone lines) runs on two 6800s, one of which is a
>> hot spare. But of course there's a large lump of hardware that's routing
>> the individual bytes here and there, so the 6800 only actually gets
>> involved when you connect or disconnect, basically.
>
> Wait, a 6800? As in, the chip *before* the obsolete 68000?
Yes.
> Damn. If the actual switching is in hardware, that the heck do you need
> the CPU for at all?
For deciding what to connect. You pick up the phone? The 6800 connects your
phone to the dial-tone generator. It's not sitting there generating the
waveform in software. You push a button? The 6800 routes your line to the
DTMF decoder, which signals the 6800 each time you let go of the tone. When
you've dialed enough numbers, the 6800 figures out what line you're supposed
to connect to and plugs you through.
> Actually, one of the reasons I wanted to learn about Erlang was to see
> if I can design something that does the same thing, but isn't insane.
Check out Hermes first. :-)
> Well, yeah, I meant for pattern matching against a value. Receiving
> messages as a bit special.
Right.
> OK. So that's why the state is explicitly threaded (quite apart from
> Erlang apparently having no other way to handle running state). That
> still doesn't explain why I can't put several related behaviours into a
> single module. Perhaps I *want* to replace them all at the same time.
I don't know. Go work for Erricson. ;-)
>>> Many things about Erlang still remain unexplained. I still have
>>> absolutely no clue WTF an "atom" is.
>>
>> An atom is an interned string. Same as a "symbol" in LISP or Smalltalk.
>> The trick is that in a message, an atom is an index into the atom table,
>> so it's short regardless of how long the atom is.
>
> I never really understood what an interned string is. (And hence what
> the difference between a Smalltalk string and a symbol is.)
I explained this for Warp a couple weeks ago. An interned value is a
reference value where reference equality equals value equality.
Or, in normal speak, an interned string is one where there's only one copy
of any given string, so you can compare the addresses where two strings are
stored and tell if they're equal.
In Erlang, you can think of an atom as one element of a giant global enum of
all the atoms you've ever used in your program. It's nothing more than an
index into a table that happens to be readable.
> So you're saying that the compiler replaces all occurrences of an atom
> with a pointer to a single instance of the string? (And hence, you can
> compare atoms for equity by simple pointer equity rather than string
> comparison.)
Basically, that's what an interned string is. An "atom" is implemented as an
interned string, but it's syntactically different. It's ... an atom. It's a
string treated as a single atomic value. You can't ask for the third
character of an atom, for example.
>>> Nor have I discovered what this "OTP" thing that gets mentioned every
>>> 3 sentences is.
>>
>> It's the libraries that take the basic operations Erlang supplies (like
>> "load new code" or "spawn link") and turn it into things like
>> installable packages.
>
> Right, OK. So what does it mean when they say "the compiler is an OTP
> application"?
It means the compiler is a function in the OTP libraries that you invoke in
order to compile the code.
> OK, so, I can register a PID with a particular name. Is that name local
> to just that node? Does every node in the system know about it? How do
> you avoid registering a name that some unrelated application has already
> registered? If I ask for a particular name, how does it figure out which
> node that's on? If a node goes down, does the name get taken out of
> service? How do you handle the same service being available from several
> nodes? (For load-balancing or fault tolerance, perhaps.)
I don't remember all this stuff. Registering as a known name passes your
mailbox and the name to a process that proceeds to distribute it and answer
queries about it. You can look at the documentation for it to see what it does.
>> It's basically a distributed transactional system on top of the built-in
>> database tables whose TLA name escapes me at the moment.
>
> Right.
ETS is the name of the sub-system functions.
>> Note that all these things, OTP and Mnesia, along with stuff like the
>> compiler, the debugger, the profiler, the package manager, etc etc etc,
>> are all documented as "here's the functions you use to do it in Erlang."
>> Almost none of these things are actually command-line tools.
>
> Nothing wrong with that. The question is how much detail the
> documentation explains. ;-)
The other problem is that all the documentation assumes you've read the
previous documentation and knows what they're talking about, but it doesn't
actually give you pointers to any of the previous documentation.
So if you want to use mnesia, you read mnesia, but it assumes you know what
ets and gen_server are and etc. So mnesia will have a function and say "this
only works on ram_raw tables" or "that function starts a new server" and
assume that you know "ram_raw" is something that ets implements (not Mnesia)
and that a 'server' in this context specifically means a gen_server module.
You'd like mnesia, tho. It's a lot like STM in some ways.
--
Darren New, San Diego CA, USA (PST)
"How did he die?" "He got shot in the hand."
"That was fatal?"
"He was holding a live grenade at the time."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible wrote:
> An object/relational hybrid "suitable for telecommunications applications"?
By which they mean reliable, distributed, fairly fast, keeps everything in
RAM, and expects to run continuously, but which there aren't going to be any
ad hoc queries.
> It says it has "extremely fast real-time searches", but it also says
> that the query language is "an add-on library"?
I guess it's extremely fast real-time searches *if* you know exactly what
you're going to search for. Otherwise, it does a full table lock-and-scan
without any optimization. And you have to maintain your own indexes, so
after you insert the record into the table, you have to insert the key into
each index as well.
The query language isn't the functions used to access the tables. It's sort
of like saying "We have really fast loops and comparisons. List
comprehensions are an add-on library."
> Reading the rest of the documentation just made my head hurt. I
> particularly love how a "table" can be "set", "ordered set" or "bag",
> but only the first and last option are explained.
That's exactly what I'm saying. You're expected to know that "set" and
"ordered set" and "bag" are the three different types of ets tables, and go
read the ets documentation to figure out what that is.
> A reference manual is no way to learn how to use a complex system.
In this case, the other choice is to go work for Ericson, it seems.
--
Darren New, San Diego CA, USA (PST)
"How did he die?" "He got shot in the hand."
"That was fatal?"
"He was holding a live grenade at the time."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
the real mistery of Erlang is the name: at first I thought it was for
"Ericsson Language". But then I heard they were actually paying homage
to one of the pioneers of traffic engineering and related telophony techs:
http://en.wikipedia.org/wiki/Agner_Krarup_Erlang
--
a game sig: http://tinyurl.com/d3rxz9
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On 10/03/2011 07:32 PM, nemesis wrote:
> the real mistery of Erlang is the name:
The real mystery of Erlang is that it was *banned* from Ericsson at one
point...
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> Erlang is partially functional, in that functions are apparently
>> first-class, and it's got single-assignment and immutable data
>> structures.
>
> Functions in C are first class. That doesn't mean it's functional.
In C it's not especially easy to write a half-line anonymous function
and pass that as the argument to something. In fact, function pointers
are probably the number #1 thing about C that I can't figure out how to
work, but presumably this only affects me...
> The
> immutable data structures come from the single-assignment, except where
> the data structures aren't immutable, of which there are several.
I wasn't aware that there are any mutable data structures. Then again, I
read an introductory design document, so...
> Well, that's the killer. To me, if every statement can have
> side-effects, then it's not a functional language.
Depends on your definition of "functional". Some people say that
first-class functions is the definitive thing. Others claim it's
referential transparency. A few people even claim it's the type system
or the syntax...
> You have none of the benefits and all of the
> draw-backs of a functional language in Erlang.
Awesome.
>> The document I
>> read claims that it's considered beneficial to limit side-effects to
>> just a few places in the codebase,
>
> Except that message sending and message receiving are both side-effects
> as is spawning or linking another process, so that works pretty poorly.
The guy goes on to point out that by using gen_server, your code has no
explicit message passing or process linking at all, and this is an
extremely awesome thing because it means that your own code is free of
side-effects.
> Plus, as I said, having the side-effects means you cannot (for example)
> use your own functions in guards.
Oh... my god.
> For some reason, the Erlang enthusiasts think the crappy syntax and the
> single-assignment procedures are intentional and beneficial properties
> of the language. Like any niche language, the fanboi's refuse to accept
> that any compromise was made during its design.
I'm not sure a language with multi-billion lines of code in
mission-critical production applications can be considered "niche".
> Actually, in the documentation, I think there's a note on each built in
> function that says whether you can use it in a guard or not.
Fail.
>> One data point is scientific fact?
>
> It's a scientific fact that you can achieve nine 9's of uptime over the
> course of a decade with programs written in Erlang, yes. Pretty sure
> that's really, really hard to do with any other programming language.
Do we know that it isn't really, really hard to do in Erlang too? I
mean, one system did it, but how much time, money and effort did they
throw at the problem?
Now show that using something other than Erlang would have required
/more/ time, money and effort, and we have something resembling a proven
fact. ;-) Now repeat this for more than one system...
>> As I say, this doesn't really seem to be spelled out anywhere else
>> that I could find, and it seems a rather crucial detail.
>
> It's kind of in all the books and stuff. I think the PhD thesis is
> presumed required reading, if nothing else.
"The" PhD thesis?
>> (Quite how you tell the difference between an exception and a normal
>> result is left to the imagination...
>
> Well, an exception will start with EXIT, while a regular result is
> unlikely to, unless you specifically confuse things that way.
It just looks like the sort of thing I might do by mistake, spend 20
minutes wondering why my application is acting screwy, and then have a
little facepalm moment.
(E.g., one time I was building a Smalltalk application, and I wanted
certain building blocks of the application to have names that would
display on the screen. Obviously the name of a FirstOrderFilter doesn't
change for each instance, so I added a class method called #name... All
kinds of fun erupted after that. Eventually I discovered that the Class
metaclass already /has/ a #name method, or something like that. Ouch!)
>> You mean that if message #5 doesn't arrive, message #6 is actually
>> guaranteed not to arrive?
>
> If message #5 didn't arrive because the receiving machine crashed, yes,
> message #6 isn't going to be received either. If message #5 didn't
> arrive because the network switch died, then #6 isn't going to be
> delivered either.
Presumably if the link dies and then comes back, or any other
combination of circumstances, either the TCP link is still alive (in
which case it resents #6 *and* #5), or the link has been broken (in
which case neither message arrives).
> Yes, exactly. More precisely, you can't tell if the message was received
> and processed or not.
OK.
>> These people are /serious/ about reliability. o_O
>
> Well, yes, that's how you get 5 minutes of downtime over the course of
> 10 years.
Some people might refer to that as "luck". ;-) Apparently there are
Windows 95 systems with this kind of uptime.
> Well, not quite. If the network between the machines dies, each machine
> is going to think the other crashed. This makes a mess.
"Ow, I don't care *what* universe you're from, that had to hurt!"
>> Thing is, I can open the REPL and type in a function, and then ask to
>> spawn that on a remote node. How does *that* work?!
>
> Hmmm. Actually, I think perhaps it *is* willing to ship functions
> around. The details escape me at the moment. Maybe you can send
> functions but not modules? I don't honestly remember.
Or maybe if you do this, it just tells you to sod off. I don't know...
>> I'll bet. No doubt somebody has written libraries for other languages
>> to speak the same wire protocol.
>
> I don't know. Probably, but I'm not sure why you would.
There are libraries that implement BEEP, even though nobody ever uses
it. I'm *sure* there are libraries for a massively successful thing like
Erlang. ;-)
>> I'm not actually sure why though.
>
> Reliability. ;-)
In what way is this more reliable?
>> You would think that a fully interconnected mesh would quickly exhaust
>> the supply of TCP ports too.
>
> Unless you have more than 50,000 machines, unlikely.
Hmm, yes. The number of links rises exponentially, not the number of
links per node.
> One of the OTP functions shows how to authenticate and encrypt the
> connection en Erlang code, IIRC. That's also one of the tutorials.
>
> Actually, I had forgotten. There is a "cookie" you can set, and anyone
> connecting needs the same "cookie". So there is a minimal security
> level, not unlike the similar feature in X servers.
And the "cookie" is presumably sent unencrypted from node to node when
they try to connect too.
BTW, how do you identify a remote node? Is it just by DNS name or IP
address or something?
> What, you're believing fanboi's?
Doesn't everything? ;-)
>>> The two-versions limit is because the code itself isn't GCed. They
>>> document that they could have GCed the code, but that would have added
>>> lots of overhead for something relatively rare.
>>
>> Fair enough.
>
> Plus, you should be dealing with the occasional "process suddenly ends
> for no reason" exception robustly anyway. :-)
Layers within layers of crash recovery... :-}
> I found it annoying that there's no global roadmap. So you read about
> something and it says "If X happens, a message is sent to the error
> logger." WTF is the error logger? Where's the documentation. Then you
> track that down, and it's all talking about bits and pieces that are
> also not documented, etc, with the assumption that you have a bunch of
> people who wrote the error logger hanging around to tell you how to find
> where the errors got logged and such.
An error logger where you can't find the log? Oh, that's epic! :-D
Honestly, I thought only Haskell does this kind of stupidity...
(Yesterday, the new version of the Haskell Platform was released. Which
is just as well, because the home page has been saying that the next
release is due in "January 2011" for several months now.)
>> Escaped experiment, eh? ;-)
>
> That's exactly what it was. Except that by the time it escaped, there
> were millions of lines of production code written in it, so you couldn't
> even reasonably fix it.
Well, you can do syntax changes with a conversion program. But
large-scale language changes? No, not really, no.
>> The advice presumably being that workers should only receive "real"
>> messages, and supervisors should only receive exceptions. Then there
>> can be no ambiguity. (Until the supervisor's supervisor asks it to do
>> something...)
>
> Well, more like, normal worker processes shouldn't communicate with
> messages that start with the atom "EXIT". It's not that hard.
It looks like the sort of mistake I would eventually make, and then
spend a seriously long time trying to debug. Maybe being all upper-case
is enough to prevent this, I don't know...
> Hermes gives you as many mailboxes as you want, with as many connections
> to each mailbox as you want, and you can send both connections and
> mailboxes in messages to other processes. So if you want hot-swap code,
> write your processes as being capable of packaging up its mailboxes and
> sending them to a new process.
OK.
>> So you're saying that all the "interesting" stuff like the SSL
>> implementation is actually just an off-the-shelf C library?
>
> It's possible.
What, you mean you don't *know*? Isn't this *documented* somewhere? ;-)
>> I never did understand what's so great about Tk. It looks horrid, it's
>> really hard to use, and it's almost impossible to get the layout you
>> want...
>
> Well, no, it's really easy to use, it's easy to get a good-looking
> layout, and it only looks horrid because it looked cutting-edge 10 years
> ago and nobody ever improved the look of it since then. (Altho they've
> worked on that more lately.)
>
> That's exactly why half a dozen non-Tcl languages actually went so far
> as to embed a Tcl interpreter into their code in order to be able to use
> Tk. I'm pretty sure it's not Tk that's at fault here. ;-)
That's like saying "C is a fantastic language, it's really easy to use,
and that's why 90% of all software ever written uses it. I don't think C
is at fault here."
>> Damn. If the actual switching is in hardware, that the heck do you
>> need the CPU for at all?
>
> For deciding what to connect. You pick up the phone? The 6800 connects
> your phone to the dial-tone generator. It's not sitting there generating
> the waveform in software. You push a button? The 6800 routes your line
> to the DTMF decoder, which signals the 6800 each time you let go of the
> tone. When you've dialed enough numbers, the 6800 figures out what line
> you're supposed to connect to and plugs you through.
That's seriously the only reason why it has a Turing-complete processing
unit inside it?
Man, you would have thought QBASIC would be enough for _that_ level of
functionality...
> I don't know. Go work for Erricson. ;-)
Worst FAQ answer *ever*! :-D
> It means the compiler is a function in the OTP libraries that you invoke
> in order to compile the code.
FWIW, I wish more languages were implemented like this...
(I'm just bitter because I spent yesterday trying to figure out how to
get GHC to compile and optimise some source code, and then give me the
AST. Which I managed, BTW, but trying to figure out WTF the AST actually
means? Ugh!)
> You can look at the documentation for it to see what it does.
At this point, I don't hold out a lot of hope... o_O
> The other problem is that all the documentation assumes you've read the
> previous documentation and knows what they're talking about, but it
> doesn't actually give you pointers to any of the previous documentation.
I hate that. The Oracle documentation is like this too. Even the
chapters in a single document refer to things out of sequence. Like, in
chapter 1, it uses technical terms that aren't explained until chapter
2, and chapter 2 uses things that were explained in chapter 1, but the
explanation in chapter 1 doesn't make sense until you read chapter 3
anyway. WHO WROTE THIS CRAP?!
Still, it could be worse. Consider the following quotation from one of
the Haskell standard libraries:
http://www.haskell.org/ghc/docs/6.6/html/libraries/mtl/Control-Monad-Writer.html
"Inspired by the paper Functional Programming with Overloading and
Higher-Order Polymorphism, Mark P Jones (http://www.cse.ogi.edu/~mpj/)
Advanced School of Functional Programming, 1995."
(Notice that the URL no longer exists.)
I emphasise: /standard libraries/. Not even some exotic add-on library.
One of the base libraries that comes with the compiler. And there's not
one single line of human-written text on that page, beyond the reference
to the paper where this stuff is actually explained.
> You'd like mnesia, tho. It's a lot like STM in some ways.
Except the part where there's at least 3 extensive yet readable
technical introductions to what it does, why you'd want that, and how
you use it, with full example source code and explanations. ;-)
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible wrote:
> In C it's not especially easy to write a half-line anonymous function
I didn't say it was convenient. I said it was first class.
>> immutable data structures come from the single-assignment, except where
>> the data structures aren't immutable, of which there are several.
>
> I wasn't aware that there are any mutable data structures. Then again, I
> read an introductory design document, so...
ETS and the process dictionary both spring to mind.
> Depends on your definition of "functional". Some people say that
> first-class functions is the definitive thing. Others claim it's
> referential transparency. A few people even claim it's the type system
> or the syntax...
I can't think of any language nowadays that doesn't have first class
functions. COBOL and FORTRAN, maybe, but that's about it.
I've never heard "functional" actually mean anything except "what you write
is functions", as in, mapping inputs to outputs. Anything mutable makes it
non-functional.
> The guy goes on to point out that by using gen_server, your code has no
> explicit message passing or process linking at all, and this is an
> extremely awesome thing because it means that your own code is free of
> side-effects.
Yes. gen_server separates out the functional part from the non-functional
part. But that doesn't give Erlang itself any benefits. No doubt functional
programming is easier to debug. You just have to manually separate it out
from the rest of the non-functional stuff.
>> Plus, as I said, having the side-effects means you cannot (for example)
>> use your own functions in guards.
>
> Oh... my god.
Yes, exactly. Still think it's functional?
>> For some reason, the Erlang enthusiasts think the crappy syntax and the
>> single-assignment procedures are intentional and beneficial properties
>> of the language. Like any niche language, the fanboi's refuse to accept
>> that any compromise was made during its design.
>
> I'm not sure a language with multi-billion lines of code in
> mission-critical production applications can be considered "niche".
It's niche, as much as formula-1 race cars are niche cars in spite of being
famous and wildly expensive. ERlang's niche is telecom programs that run for
decades without crashing.
>> It's a scientific fact that you can achieve nine 9's of uptime over the
>> course of a decade with programs written in Erlang, yes. Pretty sure
>> that's really, really hard to do with any other programming language.
>
> Do we know that it isn't really, really hard to do in Erlang too? I
> mean, one system did it, but how much time, money and effort did they
> throw at the problem?
Well, let's rephrase that. It's certainly easier in Erlang than it would be
in straight C. :-)
> Now show that using something other than Erlang would have required
> /more/ time, money and effort, and we have something resembling a proven
> fact. ;-) Now repeat this for more than one system...
Look up the history of NIL. Then look up the history of Hermes. Now you have
three similarly-organized systems that all show you can run long-term
mixed-developer systems reliably by using these techniques.
Do you think Ericson had *not* been trying to come up with this system
before they wrote millions of lines of code in it? Do you think they
wouldn't have started using a different system if Erlang didn't give them
the benefits they expected?
>
>>> As I say, this doesn't really seem to be spelled out anywhere else
>>> that I could find, and it seems a rather crucial detail.
>>
>> It's kind of in all the books and stuff. I think the PhD thesis is
>> presumed required reading, if nothing else.
>
> "The" PhD thesis?
Armstrong's PhD thesis.
>>> (Quite how you tell the difference between an exception and a normal
>>> result is left to the imagination...
>>
>> Well, an exception will start with EXIT, while a regular result is
>> unlikely to, unless you specifically confuse things that way.
>
> It just looks like the sort of thing I might do by mistake, spend 20
> minutes wondering why my application is acting screwy, and then have a
> little facepalm moment.
I didn't use Erlang very much, and it never occurred to me to use an atom in
all upper case, let alone one that says 'EXIT'.
> (E.g., one time I was building a Smalltalk application, and I wanted
> certain building blocks of the application to have names that would
> display on the screen. Obviously the name of a FirstOrderFilter doesn't
> change for each instance, so I added a class method called #name... All
> kinds of fun erupted after that. Eventually I discovered that the Class
> metaclass already /has/ a #name method, or something like that. Ouch!)
Name clash of methods? Sure. Name clash of values you're returning against
the three or four already-defined values? No. Treat it as a reserved word.
This is exactly why so many messages returned start with "ok".
> Presumably if the link dies and then comes back, or any other
> combination of circumstances, either the TCP link is still alive (in
> which case it resents #6 *and* #5), or the link has been broken (in
> which case neither message arrives).
Yes.
> Some people might refer to that as "luck". ;-) Apparently there are
> Windows 95 systems with this kind of uptime.
No there aren't. All the 16-bit Windows machines had a seconds counter that
wrapped after 42 days and crashed the computer.
>>> I'll bet. No doubt somebody has written libraries for other languages
>>> to speak the same wire protocol.
>>
>> I don't know. Probably, but I'm not sure why you would.
>
> There are libraries that implement BEEP, even though nobody ever uses
> it.
Actually, I'm rather surprised at the number of people who use
syslog-reliable (which runs over BEEP) let alone BEEP itself. What makes you
think nobody uses BEEP?
>>> I'm not actually sure why though.
>> Reliability. ;-)
> In what way is this more reliable?
If you lose a connection to a node, you can ask the other nodes if they lost
a connection too, for one thing. And if A connects to B, then B passes a
connection to C to A, A needs a connection to C anyway. You don't want to
wait till that point for A to find out it is firewalled from C.
> And the "cookie" is presumably sent unencrypted from node to node when
> they try to connect too.
No, the cookie doesn't get sent at all.
> BTW, how do you identify a remote node? Is it just by DNS name or IP
> address or something?
http://www.erlang.org/doc/reference_manual/distributed.html#id80719
The documentation *is* online.
>> Plus, you should be dealing with the occasional "process suddenly ends
>> for no reason" exception robustly anyway. :-)
>
> Layers within layers of crash recovery... :-}
Incidentally, NIL worked it where you declared which processes were a group,
and you could kill them off or roll them over as a group. So you didn't have
the problem of one module being upgraded while another module isn't.
> An error logger where you can't find the log? Oh, that's epic! :-D
I'm sure you can find it if you can figure out which module it talks to. But
it's like .NET, where debugging output goes to the configured output
methods, and if you haven't configured them, it disappears. If you're used
to (say) C's assert() macro, finding out you have to configure where assert
messages go on a run-by-run basis is rather disconcerting if you didn't even
think to look.
> It looks like the sort of mistake I would eventually make, and then
> spend a seriously long time trying to debug. Maybe being all upper-case
> is enough to prevent this, I don't know...
Why do you make mistakes like that? How often do you write code and use
reserved works as variable names?
> What, you mean you don't *know*? Isn't this *documented* somewhere? ;-)
It's in the source code. Welcome to open source!
> That's like saying "C is a fantastic language, it's really easy to use,
> and that's why 90% of all software ever written uses it. I don't think C
> is at fault here."
No, because there really wasn't much of an alternative to C for many years.
People tried many alternatives, and they all sucked so bad they never really
got out of the lab. So clearly C is doing something right.
> That's seriously the only reason why it has a Turing-complete processing
> unit inside it?
I don't know what else it does. Billing records, managing the configuration
changes, etc. The point is it's not switching individual voice packets, any
more than your CPU is getting involved in deciding which ethernet packets
going past are addressed to the machine the ethernet card is plugged into.
>> It means the compiler is a function in the OTP libraries that you invoke
>> in order to compile the code.
>
> FWIW, I wish more languages were implemented like this...
Well, that's the next version of .NET. I think it's cool. I wish people who
weren't using Microsoft could use it as easily.
> (I'm just bitter because I spent yesterday trying to figure out how to
> get GHC to compile and optimise some source code, and then give me the
> AST. Which I managed, BTW, but trying to figure out WTF the AST actually
> means? Ugh!)
Erlang can hand you the AST for you to run macro preprocessign on at compile
time. (That's how records work, for example.) You think figuring out the AST
when you have a *statically* typed language is hard?
> Except the part where there's at least 3 extensive yet readable
> technical introductions to what it does, why you'd want that, and how
> you use it, with full example source code and explanations. ;-)
http://www.erlang.org/doc/apps/mnesia/users_guide.html
Were you maybe reading the reference manual instead of the user's guide?
--
Darren New, San Diego CA, USA (PST)
"How did he die?" "He got shot in the hand."
"That was fatal?"
"He was holding a live grenade at the time."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible <voi### [at] dev null> wrote:
> - There are many functional programming languages. (Haskell, OCaml,
> Clean, and for some reason people keep calling Lisp "functional" too.)
Why did you not mention Lisp? It's the first, and still considered by
many to be *The* functional language.
> However, Erlang is *the only* one that could be considered "commercially
> successful", as far as I can tell.
How about Lisp?
> Suffice it to say, from what little I could discover, I didn't like what
> I was seeing. Like most commercially successful languages, Erlang is
> obtuse, complex, ugly and kludgy. Much like C, Java or anything else
> wildly popular.
Can you name a programming language that isn't? (Besides Lisp.)
And don't say "Haskell". I can understand a Java program much more
easily than a Haskell one. So much for obtuse, complex and ugly.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On 11/03/2011 05:53 PM, Warp wrote:
> Invisible<voi### [at] dev null> wrote:
>> - There are many functional programming languages. (Haskell, OCaml,
>> Clean, and for some reason people keep calling Lisp "functional" too.)
>
> Why did you not mention Lisp?
Ummm... I *did*? It's right there in the quote.
> It's the first, and still considered by
> many to be *The* functional language.
I can't figure out why. Functions are first-class in Lisp, but beyond
that there's nothing functional about it. (Unless you think "it uses
lists" has something to do with being functional...)
>> However, Erlang is *the only* one that could be considered "commercially
>> successful", as far as I can tell.
>
> How about Lisp?
I wasn't aware that there are any multi-million line mission-critical
production-grade systems written in Lisp. I suppose there might be
somewhere. I'm certainly not aware of any well-known commercial entities
telling everybody that they should use Lisp.
>> Suffice it to say, from what little I could discover, I didn't like what
>> I was seeing. Like most commercially successful languages, Erlang is
>> obtuse, complex, ugly and kludgy. Much like C, Java or anything else
>> wildly popular.
>
> Can you name a programming language that isn't? (Besides Lisp.)
No, I'd say Lisp is kludgy too.
> And don't say "Haskell". I can understand a Java program much more
> easily than a Haskell one. So much for obtuse, complex and ugly.
There are people who describe mathematical equations as being obtuse,
complex and ugly. And there are others who describe them as being
sublimely beautiful, even transcendental. Wanna guess which side I'm on?
Beauty is of course in the eye of the beholder, so I won't argue about
this further.
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> Depends on your definition of "functional". Some people say that
>> first-class functions is the definitive thing. Others claim it's
>> referential transparency. A few people even claim it's the type system
>> or the syntax...
>
> I can't think of any language nowadays that doesn't have first class
> functions. COBOL and FORTRAN, maybe, but that's about it.
Java? Eiffel?
> Yes. gen_server separates out the functional part from the
> non-functional part. But that doesn't give Erlang itself any benefits.
> No doubt functional programming is easier to debug. You just have to
> manually separate it out from the rest of the non-functional stuff.
Indeed. It lets you write in a functional style, but doesn't force you
to. I suppose some people will claim that's "pragmatic".
>> Oh... my god.
>
> Yes, exactly. Still think it's functional?
Personally, no...
>> I'm not sure a language with multi-billion lines of code in
>> mission-critical production applications can be considered "niche".
>
> It's niche, as much as formula-1 race cars are niche cars in spite of
> being famous and wildly expensive. ERlang's niche is telecom programs
> that run for decades without crashing.
Sure. But people often reverse the word "niche" as a kind of polite way
of saying "hopelessly unsuccessful". ;-)
>>> It's a scientific fact that you can achieve nine 9's of uptime over the
>>> course of a decade with programs written in Erlang, yes. Pretty sure
>>> that's really, really hard to do with any other programming language.
>>
>> Do we know that it isn't really, really hard to do in Erlang too?
>
> Well, let's rephrase that. It's certainly easier in Erlang than it would
> be in straight C. :-)
People claim that Unix (or maybe specificaly Linux) is insanely
reliable, and that's almost all pure C.
> Do you think Ericson had *not* been trying to come up with this system
> before they wrote millions of lines of code in it? Do you think they
> wouldn't have started using a different system if Erlang didn't give
> them the benefits they expected?
I'm sure Ericsson things that Erlang is great. That's not "scientific"
necessarily though. ;-) I'm not seriously disagreeing with you, just the
fanboys.
>> "The" PhD thesis?
>
> Armstrong's PhD thesis.
I wonder if that's the document I just read, or a different one...
>> It just looks like the sort of thing I might do by mistake, spend 20
>> minutes wondering why my application is acting screwy, and then have a
>> little facepalm moment.
>
> I didn't use Erlang very much, and it never occurred to me to use an
> atom in all upper case, let alone one that says 'EXIT'.
> This is exactly why so many messages returned start with "ok".
So many, BUT NOT ALL. It seems to vary inconsistently. Sometimes there's
an atom to tell you whether it was OK or not, and sometimes there's only
an atom to tell you when it failed.
>> Some people might refer to that as "luck". ;-) Apparently there are
>> Windows 95 systems with this kind of uptime.
>
> No there aren't. All the 16-bit Windows machines had a seconds counter
> that wrapped after 42 days and crashed the computer.
Got a reference for that?
>>>> I'm not actually sure why though.
>>> Reliability. ;-)
>> In what way is this more reliable?
>
> If you lose a connection to a node, you can ask the other nodes if they
> lost a connection too, for one thing.
Oh, I see.
> And if A connects to B, then B
> passes a connection to C to A, A needs a connection to C anyway.
What makes you think that?
>> And the "cookie" is presumably sent unencrypted from node to node when
>> they try to connect too.
>
> No, the cookie doesn't get sent at all.
So how do you compare it then?
>> BTW, how do you identify a remote node? Is it just by DNS name or IP
>> address or something?
>
> http://www.erlang.org/doc/reference_manual/distributed.html#id80719
>
> The documentation *is* online.
Right. So it's DNS name, plus a user-defined atom (presumably so you can
run several nodes on a single machine).
>> It looks like the sort of mistake I would eventually make, and then
>> spend a seriously long time trying to debug. Maybe being all
>> upper-case is enough to prevent this, I don't know...
>
> Why do you make mistakes like that? How often do you write code and use
> reserved works as variable names?
More often than you'd think. For example, I might try to use "if" for
"input file" and "of" for "output file". Shame both of those are
reserved words in Haskell. But - fortunately - this causes a
compile-time error in Haskell. You say "treat special atoms as reserved
words", but if they really were reserved words, you'd get a compile-time
error informing you of your mistake, rather than mysterious run-time
behaviour which possibly only shows up under unusual conditions.
>> What, you mean you don't *know*? Isn't this *documented* somewhere? ;-)
>
> It's in the source code. Welcome to open source!
EPIC FAILURE. >_<
>> That's like saying "C is a fantastic language, it's really easy to
>> use, and that's why 90% of all software ever written uses it. I don't
>> think C is at fault here."
>
> No, because there really wasn't much of an alternative to C for many
> years. People tried many alternatives, and they all sucked so bad they
> never really got out of the lab. So clearly C is doing something right.
That's the actual reason? I've often wondered about this, but it was a
long time ago when all this stuff presumably happened...
>> That's seriously the only reason why it has a Turing-complete
>> processing unit inside it?
>
> I don't know what else it does. Billing records, managing the
> configuration changes, etc. The point is it's not switching individual
> voice packets, any more than your CPU is getting involved in deciding
> which ethernet packets going past are addressed to the machine the
> ethernet card is plugged into.
Wait - the CPU on my PC *doesn't* process the incomming packets??
> Erlang can hand you the AST for you to run macro preprocessign on at
> compile time. (That's how records work, for example.) You think figuring
> out the AST when you have a *statically* typed language is hard?
Strictly, what I'm looking at isn't the parse tree of the Haskell source
code. I'm looking at the internal data structures used by the Haskell
optimiser. And it's not so much that the data is complex, it's that most
of it is complex, and it's difficult to guess where the hell the
function for examining it is defined. And the API just plain isn't very
documented. I get the impression that the inside of the compiler is just
very complex, and not especially tidy, which is surprising.
> http://www.erlang.org/doc/apps/mnesia/users_guide.html
>
> Were you maybe reading the reference manual instead of the user's guide?
Yeah, possibly.
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Orchid XP v8 wrote:
>>> Depends on your definition of "functional". Some people say that
>>> first-class functions is the definitive thing. Others claim it's
>>> referential transparency. A few people even claim it's the type system
>>> or the syntax...
>>
>> I can't think of any language nowadays that doesn't have first class
>> functions. COBOL and FORTRAN, maybe, but that's about it.
>
> Java? Eiffel?
Well, alright. You have to wrap them up in an anonymous class.
> Sure. But people often reverse the word "niche" as a kind of polite way
> of saying "hopelessly unsuccessful". ;-)
I can't help people don't know english. :-)
> People claim that Unix (or maybe specificaly Linux) is insanely
> reliable, and that's almost all pure C.
I've never heard anyone claim that. I've heard Linux people bash Windows,
and I've heard people brag about how reliable Linux is, but it's certainly
not reliable enough that it'll run ten years worth of upgrades without a
reboot or loss of service, unless you go to something like a Tandem.
> So many, BUT NOT ALL. It seems to vary inconsistently. Sometimes there's
> an atom to tell you whether it was OK or not, and sometimes there's only
> an atom to tell you when it failed.
In practice, in those routines (like catch) that return the value or an atom
if it failed, people return an atom tagging the success as well. Or they
return a different type like a list.
>>> Some people might refer to that as "luck". ;-) Apparently there are
>>> Windows 95 systems with this kind of uptime.
>>
>> No there aren't. All the 16-bit Windows machines had a seconds counter
>> that wrapped after 42 days and crashed the computer.
>
> Got a reference for that?
I'm sorry your computer can't get through to Google. I hope your
connectivity gets restored soon.
http://news.cnet.com/2100-1040-222391.html
>> And if A connects to B, then B
>> passes a connection to C to A, A needs a connection to C anyway.
> What makes you think that?
Because B may pass to A a connection to a mailbox on C.
>>> And the "cookie" is presumably sent unencrypted from node to node when
>>> they try to connect too.
>>
>> No, the cookie doesn't get sent at all.
>
> So how do you compare it then?
Oh, I see what you're asking. I assume they're smart enough not to send
passwords in the clear to machines that haven't proven they already know the
password.
>> Why do you make mistakes like that? How often do you write code and use
>> reserved works as variable names?
>
> More often than you'd think.
Wow.
>> No, because there really wasn't much of an alternative to C for many
>> years. People tried many alternatives, and they all sucked so bad they
>> never really got out of the lab. So clearly C is doing something right.
>
> That's the actual reason? I've often wondered about this, but it was a
> long time ago when all this stuff presumably happened...
C was designed to be a portable that was *not* abstracted from the machine.
Therefore, it got ported a lot, often as the first HLL ported to a new
architecture. The other languages only got ported to architectures being
used for that particular type of computing.
When people tried to make better languages than C, they tended to pile so
much extra stuff into it that would make it appropriate for both
machine-level stuff and high-level applications that it turned into a monster.
> Wait - the CPU on my PC *doesn't* process the incomming packets??
Not packets not destined for your machine, no. WTF do you think a MAC
address is for?
--
Darren New, San Diego CA, USA (PST)
"How did he die?" "He got shot in the hand."
"That was fatal?"
"He was holding a live grenade at the time."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |