From tobbe@REDACTED Sat Jan 9 05:36:46 1999 From: tobbe@REDACTED (Torbjorn Tornkvist) Date: Sat, 09 Jan 1999 15:36:46 +1100 Subject: Greeting! In-Reply-To: <32CC73CB.151C0DD4@star.daewoo.co.kr> References: <32CC73CB.151C0DD4@star.daewoo.co.kr> Message-ID: <199901090436.PAA10528@universe.serc.rmit.edu.au> > I have a Unixware system and I think it is not likely that > Erlang is going to be ported on it successfully. Why don't you try and compile it yourself ? (If Unixware is Posix compliant it wouldn't be too much of a problem I think.) > So, if I made a Erlang server program on NT where erlang system is > available and C written client program on Unixware where Eralng > system is not available, do the C-client and Erlang-server can > communicate each other successfully where > Erlang system is ported on one side(NT) only? What do you mean by a "C-client" ? Using the sockets library (gen_tcp/gen_udp) it works as you could expect. But, if you are talking about a C-node (i.e you C program acts as an distributed erlang node), then you have to compile the erl_interface library on your Unixware machine. /Tobbe From bengt.walerud@REDACTED Sat Jan 9 08:41:45 1999 From: bengt.walerud@REDACTED (Familjen Walerud) Date: Sat, 9 Jan 1999 08:41:45 +0100 Subject: SV: Commerical product in telecommunication world. Message-ID: <01BE3BAC.28901EE0.bengt.walerud@mailbox.swipnet.se> Yes, Ericsson has developed a number of products with Erlang/OTP. At the March 1998 CeBit, there were 9 products developed with Erlang/OTP on display. These products include the AXD301 ATM switch, an enterprise mobility server, the package switched IP over GSM product (GPRS), etc. As you can imagine, if Ericsson can develop an 10-160 Gigabit scalable ATM switch with Erlang, it's performance is pretty good for those applications it was designed for ( concurrent, distributed). Cheers, Jane -----Ursprungligt meddelande----- Fr?n: Freddie Kruegger [SMTP:kruegger@REDACTED] Skickat: den 3 januari 1997 08:03 Till: Erlang ?mne: Commerical product in telecommunication world. Is there any commercial telecommunication related product which was developed by Erlang(e.g. switch,SCP,IP,SDP...)? How about the performance of Erlang? From mike@REDACTED Sat Jan 9 10:08:47 1999 From: mike@REDACTED (Michael C Williams) Date: Sat, 9 Jan 1999 10:08:47 +0100 (MET) Subject: Commerical product in telecommunication world. In-Reply-To: <32CCAF07.2CC5F36A@star.daewoo.co.kr> Message-ID: On Fri, 3 Jan 1997, Freddie Kruegger wrote: > Is there any commercial telecommunication related product which was > developed by Erlang(e.g. switch,SCP,IP,SDP...)? Indeed there are several. These include Ericsson's ATM switch (about 700 000 lines of source code) and a special purpose PABX (5000 000 lines of code). But don't get the idea that Erlang is useful only for telecom products, Erlang has been used for a wide variety of applications. On avaerage the total time required to build products is about a quarter or the time used when a more conventional approach is used. this is both because of Erlang and because of the incremental design approach it allows > How about the performance of Erlang? Good enough for our extremely time critical telecoms applications! /mike From hal@REDACTED Mon Jan 11 03:59:10 1999 From: hal@REDACTED (Hal Snyder) Date: 10 Jan 1999 20:59:10 -0600 Subject: Unix and NT communicating? Message-ID: <8790fa7bwh.fsf@hippo.roxor.org> I'm probably misreading something. The question is, can Erlang systems running on Unix and Win32 communicate? For example, I'm considering connecting FreeBSD and Windows 95 systems running erlang. On the main web site, at http://www.erlang.org/download.html it says of the "Windows user" Erlang kit: Note the distribution protocol used in this release is incompatible with that used in the Unix release - this will be corrected in the next release. Is the "distribution protocol" the protocol used for inter-host communication? Because at http://www.whatis.com/erlang.htm they say Erlang's bytecode is identical on all platforms, and a network of Erlang nodes may consist of any mix of NT, UNIX, or other supported platforms. * * * Second question: what's the best way to do device control from Erlang? Suppose I wanted to talk to some PC telephony devices, e.g. Dialogic cards? Thanks. Hal From tobbe@REDACTED Mon Jan 11 04:53:43 1999 From: tobbe@REDACTED (Torbjorn Tornkvist) Date: Mon, 11 Jan 1999 14:53:43 +1100 Subject: Unix and NT communicating? In-Reply-To: <8790fa7bwh.fsf@hippo.roxor.org> References: <8790fa7bwh.fsf@hippo.roxor.org> Message-ID: <199901110353.OAA02139@universe.serc.rmit.edu.au> > I'm probably misreading something. The question is, can Erlang systems > running on Unix and Win32 communicate? For example, I'm considering > connecting FreeBSD and Windows 95 systems running erlang. Ok, there is a little confusion here what we mean when we talk about communicating between Unix and Windows using Erlang. ----- Using the Erlang built-in support to communicate between two or more Erlang nodes (which may be running on different platforms such as Unix, Windows, etc...), means that we can, from one Erlang node, spawn a new Erlang process on another Erlang node, send messages to an other Erlang node, setup links to other Erlang nodes etc... This mechanism uses the built-in Erlang distribution protocol (which runs on top of TCP). As it seems *today*, there are inconsistent versions of the distribution protocol for the Unix and Window port of Erlang. This makes it not possible to communicate between such Erlang nodes. This is probably a very easy fix, which (again probably) will be provided real soon now... (?) ----- The other way to communicate between different Erlang nodes is to use the Socket support. See the Erlang man pages for the Erlang modules gen_tcp and gen_udp for how to setup TCP/UDP connections to other Erlang nodes (or other TCP/UDP software). ----- > Second question: what's the best way to do device control from Erlang? > Suppose I wanted to talk to some PC telephony devices, e.g. Dialogic > cards? I know that this has been done using Dialogics card, so someone will probably come with a more elaborated answer. Basically, you write a C program which you start from Erlang with the open_port/2 BIF. The C program relays the data sent between your device and your Erlang node. This C program can either be run as a stand-alone program (e.g in a separate Unix process) or as an Erlang linked in driver. (My advice is to first develop and test it as a stand-alone program) This Erlang/C interface can be written by hand or be generated (more or less) automatically using the IC or the IG application. See the documentation. I have myself only used IG (the Interface Generator) and can give you more feedback on how to use it if needed. Some old (but nice ;-) IG documentation can be found at: http://www.serc.rmit.edu.au/~tobbe/ig.html /Tobbe From joe@REDACTED Mon Jan 11 08:11:46 1999 From: joe@REDACTED (Joe Armstrong) Date: Mon, 11 Jan 1999 08:11:46 +0100 (MET) Subject: Commerical product in telecommunication world. In-Reply-To: <32CCAF07.2CC5F36A@star.daewoo.co.kr> Message-ID: On Fri, 3 Jan 1997, Freddie Kruegger wrote: > Is there any commercial telecommunication related product which was > developed by Erlang(e.g. switch,SCP,IP,SDP...)? Yes many. You can read about some of them in http://www3.ericsson.se/SE/kon_con/contact/cebit/cebit20.html > > How about the performance of Erlang? > Jolly fast for our kind of applications. No so good for pure "number cruching". /Joe -- Joe Armstrong Computer Science Laboratory +46 8 719 9452 AT2/ETX/DN/SU Ericsson Telecom SE-126 25 Stockholm Sweden joe@REDACTED http://www.ericsson.se/cslab/~joe From joe@REDACTED Mon Jan 11 09:20:13 1999 From: joe@REDACTED (Joe Armstrong) Date: Mon, 11 Jan 1999 09:20:13 +0100 (MET) Subject: Unix and NT communicating? In-Reply-To: <8790fa7bwh.fsf@hippo.roxor.org> Message-ID: On 10 Jan 1999, Hal Snyder wrote: > I'm probably misreading something. The question is, can Erlang systems > running on Unix and Win32 communicate? For example, I'm considering > connecting FreeBSD and Windows 95 systems running erlang. > > On the main web site, at http://www.erlang.org/download.html it says > of the "Windows user" Erlang kit: > > Note the distribution protocol used in this release is incompatible > with that used in the Unix release - this will be corrected in the > next release. > > Is the "distribution protocol" the protocol used for inter-host > communication? > Yes > Because at http://www.whatis.com/erlang.htm they say > > Erlang's bytecode is identical on all platforms, and a network of > Erlang nodes may consist of any mix of NT, UNIX, or other supported > platforms. > Sorry for the confusion. Let me explain in more detail... All Erlang nodes (a node is a complete Erlang system running on some platform) can communicate in a transparent manner. For example on an NT machine you could send a arbitrary Erlang message to any other machine (solaris, freeBSD etc). A couple of weeks before the OSE release we discovered a security hole in the system and changed the implementation to deal with this. We got as far as making the changes for the unix systems, but NOT for the WIN32 systems. So all the unix systems CAN talk transparently to each other but they will not be able to talk to the WIN32 system. The Win32 build is more painful than the unix build so we distributed the unix source + makefiles (with the new security fixed protocol) and the win32 binaries (with the old protocol). These two systems cannot talk to each other. Last week tony (tony@REDACTED) successfully built the win32 system so that it can talk to the unix systems... We will put this on the web site ASAP. Mail tony for more info. > * * * > > Second question: what's the best way to do device control from Erlang? > Suppose I wanted to talk to some PC telephony devices, e.g. Dialogic > cards? See tobbe's answer /Joe -- Joe Armstrong Computer Science Laboratory +46 8 719 9452 AT2/ETX/DN/SU Ericsson Telecom SE-126 25 Stockholm Sweden joe@REDACTED http://www.ericsson.se/cslab/~joe From ulf.wiger@REDACTED Mon Jan 11 09:35:25 1999 From: ulf.wiger@REDACTED (Ulf Wiger) Date: Mon, 11 Jan 1999 09:35:25 +0100 Subject: Greeting! References: <32CC73CB.151C0DD4@star.daewoo.co.kr> Message-ID: <3699B7CD.FF293CC4@etxb.ericsson.se> Freddie Kruegger wrote: > > Is there any benchmark test result of Erlang? The question of benchmarks comes up every once in a while, and we'd like nothing better than to have some undisputable benchmarks. Alas, they are hard to come by. The main reason is that in order to be representative, they must be so complex that noone can afford to design them. I'll clarify that. We have found that Erlang works very well for highly complex systems - systems where each designer understands only a small portion. Erlang makes the complexity much more manageable, which gives several advantages: - your chances of succeeding at all with the project increase - you gain a better understanding of the system sooner - you have experiment with different solutions - you can spot and fix quality/performance problems easier - programmers feel more empowered -> more enthusiastic All this equates somehow (although it's difficult to capture in a benchmark) to better quality, better project control, and better performance. For what it's worth, it's easy to design benchmarks that show how Erlang runs circles around JDK when it comes to concurrency. That has been done at CSlab. /Uffe -- Ulf Wiger, Chief Designer AXD 301 Ericsson Telecom AB tfn: +46 8 719 81 95 Varuv?gen 9, ?lvsj? mob: +46 70 519 81 95 S-126 25 Stockholm, Sweden fax: +46 8 719 43 44 From kruegger@REDACTED Tue Jan 5 10:11:04 1999 From: kruegger@REDACTED (Freddie Kruegger) Date: Tue, 05 Jan 1999 18:11:04 +0900 Subject: Porting Erlang on HPUX Message-ID: <3691D728.75CC1F17@star.daewoo.co.kr> Does anybody has suceeded porting Erlang on HPUX 10.XX. I got error messages while compiling base sources. Can i define not using the dynamic libraries? HP is not same as SUN so HP doesn't have dlfcn.h. From ulf.wiger@REDACTED Wed Jan 13 15:17:18 1999 From: ulf.wiger@REDACTED (Ulf Wiger) Date: Wed, 13 Jan 1999 15:17:18 +0100 Subject: rdbms-1.0 user contribution Message-ID: <369CAAEE.7A2F463B@etxb.ericsson.se> I've contributed a data dictionary to mnesia (see http://www.erlang.org/user.html) The dictionary provides: - type checks - boundary checks - verification triggers - referential integrity - a select-type access method - compound attributes - a type conversion utility (strings to specified types) - a data import tool which performs integrity checks ...and some other things. One thing I've noticed when playing with it is that it is not well documented in mnesia how to perform a series of schema operations within one schema transaction. This is obviously something that I wanted to do, since I add user properties to a table in order to support integrity checks. Here's how I've done it: create_table(Tab, MnesiaProps, UserProps) -> F = fun() -> mnesia_schema:do_create_table(Tab, MnesiaProps), rdbms:do_add_properties(UserProps) end, mnesia_schema:schema_transaction(F). Also note that I've patched mnesia_schema.erl in order to support adding multiple user properties within one transaction. The patch is included in the rdbms-1.0 package. /Uffe -- Ulf Wiger, Chief Designer AXD 301 Ericsson Telecom AB tfn: +46 8 719 81 95 Varuv?gen 9, ?lvsj? mob: +46 70 519 81 95 S-126 25 Stockholm, Sweden fax: +46 8 719 43 44 From dgud@REDACTED Wed Jan 13 15:41:19 1999 From: dgud@REDACTED (Dan Gudmundsson) Date: Wed, 13 Jan 1999 15:41:19 +0100 (MET) Subject: rdbms-1.0 user contribution In-Reply-To: <369CAAEE.7A2F463B@etxb.ericsson.se> References: <369CAAEE.7A2F463B@etxb.ericsson.se> Message-ID: <13980.45199.999590.336796@rian> Hi Ulf You want to create a table with some initial user_properties in one atomic transaction. The simplest way (unfortunately this is undocumented) to do this is: mnesia:create_table(foo, [{user_properties, Props}]). The patch of mnesia_schema is unnecessary. When it comes to nested schema transactions, you said "..it is not well documented in mnesia how to perform a series of schema operations within one schema transaction". This is true and the simple reason for not documenting that is that nested schema transactions is not a part of the public API. We do not want to encourage our customers to use our internal functions. Regards Dan, H?kan Ulf Wiger writes: > I've contributed a data dictionary to mnesia (see > http://www.erlang.org/user.html) > > The dictionary provides: > - type checks > - boundary checks > - verification triggers > - referential integrity > - a select-type access method > - compound attributes > - a type conversion utility (strings to specified types) > - a data import tool which performs integrity checks > > ...and some other things. > > > One thing I've noticed when playing with it is that it is not well > documented in mnesia how to perform a series of schema operations within > one schema transaction. > > This is obviously something that I wanted to do, since I add user > properties to a table in order to support integrity checks. > > Here's how I've done it: > > create_table(Tab, MnesiaProps, UserProps) -> > F = fun() -> > mnesia_schema:do_create_table(Tab, MnesiaProps), > rdbms:do_add_properties(UserProps) > end, > mnesia_schema:schema_transaction(F). > > Also note that I've patched mnesia_schema.erl in order to support adding > multiple user properties within one transaction. The patch is included > in the rdbms-1.0 package. > > > /Uffe > > -- > Ulf Wiger, Chief Designer AXD 301 > Ericsson Telecom AB tfn: +46 8 719 81 95 > Varuv?gen 9, ?lvsj? mob: +46 70 519 81 95 > S-126 25 Stockholm, Sweden fax: +46 8 719 43 44 > -- Dan Gudmundsson Project: Mnesia, Erlang/OTP Ericsson Telecom AB Phone: +46 8 719 7185 ETX/DN/SP Fax: +46 8 719 9101 S-126 25 Stockholm Visit addr: G?tlandsv. 218, ?lvsj? From ulf.wiger@REDACTED Wed Jan 13 16:18:25 1999 From: ulf.wiger@REDACTED (Ulf Wiger) Date: Wed, 13 Jan 1999 16:18:25 +0100 Subject: [Fwd: rdbms-1.0 user contribution] Message-ID: <369CB941.AE5983C5@etxb.ericsson.se> Oops! forgot the Cc. -- Ulf Wiger, Chief Designer AXD 301 Ericsson Telecom AB tfn: +46 8 719 81 95 Varuv?gen 9, ?lvsj? mob: +46 70 519 81 95 S-126 25 Stockholm, Sweden fax: +46 8 719 43 44 -------------- next part -------------- An embedded message was scrubbed... From: Ulf Wiger Subject: Re: rdbms-1.0 user contribution Date: Wed, 13 Jan 1999 16:17:38 +0100 Size: 2308 URL: From hakan@REDACTED Thu Jan 14 10:07:54 1999 From: hakan@REDACTED (Hakan Mattsson) Date: Thu, 14 Jan 1999 10:07:54 +0100 (MET) Subject: [Fwd: rdbms-1.0 user contribution] In-Reply-To: <369CB941.AE5983C5@etxb.ericsson.se> Message-ID: On Wed, 13 Jan 1999, Ulf Wiger wrote: Uffe> > When it comes to nested schema transactions, you said Uffe> > "..it is not well documented in mnesia how to perform a series of Uffe> > schema operations within one schema transaction". This is true and Uffe> > the simple reason for not documenting that is that nested schema Uffe> > transactions is not a part of the public API. We do not want to Uffe> > encourage our customers to use our internal functions. Uffe> Uffe> Well, there are customers and there are customers... ;) Uffe> Uffe> I don't agree with the policy that you should keep users away from a Uffe> dangerous operation by making it impossible to do, or impossible to Uffe> find. Provide a low-level interface and document clearly that you Uffe> shouldn't use it unless you know what you're doing. My intention is not to make the internal functions hard to use. But writing documentation of these have had a rather low priority. The main reason for not encouraging usage of internal functions is that their behaviour may be changed without any notice. We put no effort in making them backwards compatible. You have to be aware about that if your code uses internal functions, it may be broken in the next release. Uffe> What if I want to create 10 tables or none at all? This shouldn't be an Uffe> unusual situation. It requires being able to call all create_table/2 Uffe> functions within one transaction. Yes. It would be nice to be able to nest any combinations of schema transactions and plain table access inside an enclosing atomic transaction. Its not hard to do, but it simply has not been done yet. The plan is to remove several of the current restrictions in schema transactions in future releases. /H?kan From ulf.wiger@REDACTED Thu Jan 14 10:42:09 1999 From: ulf.wiger@REDACTED (Ulf Wiger) Date: Thu, 14 Jan 1999 10:42:09 +0100 Subject: [Fwd: rdbms-1.0 user contribution] References: Message-ID: <369DBBF1.490F6AD5@etxb.ericsson.se> Hakan Mattsson wrote: > > My intention is not to make the internal functions hard to use. But > writing documentation of these have had a rather low priority. The > main reason for not encouraging usage of internal functions is that > their behaviour may be changed without any notice. We put no effort in > making them backwards compatible. You have to be aware about that if > your code uses internal functions, it may be broken in the next > release. Indeed! It's happened to me a couple of times. That's life on the bleeding edge. (: I use the following undocumented mnesia functions in rdbms: - I fetch the transaction data directly from the process dictionary (could have used mnesia:get_activity_id(), but I didn't see it, and it's also marked as "not for public use" btw) I decided to do this since the dictionary generates read/write activity inside the transaction; if it would use mnesia:read/1 and mnesia:write/1, it would create a loop (they are forwarded back again to the dictionary for verification.) It would have been possible to work around it, but this felt like the most elegant solution. - mnesia_schema:schema_transaction/1 and mnesia_schema:do_write_table_property/2 This could perhaps have been avoided if I'd realised that there was a 'user_properties' option for create_table/2. If I figure out a way to rewrite this cleanly to use only the official API, I will of course do that. BTW, I would like to be able to specify commit() and rollback() hooks in the access module as well. I can imagine that such hooks would be dangerous, but it would allow me to write safe triggers inside the transaction. Currently, I have to wait until after commit/rollback and do a post_update trigger - not atomic. /Uffe -- Ulf Wiger, Chief Designer AXD 301 Ericsson Telecom AB tfn: +46 8 719 81 95 Varuv?gen 9, ?lvsj? mob: +46 70 519 81 95 S-126 25 Stockholm, Sweden fax: +46 8 719 43 44 From hakan@REDACTED Thu Jan 14 13:41:38 1999 From: hakan@REDACTED (Hakan Mattsson) Date: Thu, 14 Jan 1999 13:41:38 +0100 (MET) Subject: [Fwd: rdbms-1.0 user contribution] In-Reply-To: <369DBBF1.490F6AD5@etxb.ericsson.se> Message-ID: On Thu, 14 Jan 1999, Ulf Wiger wrote: Uffe> I use the following undocumented mnesia functions in rdbms: Uffe> Uffe> - I fetch the transaction data directly from the process dictionary Uffe> (could have used mnesia:get_activity_id(), but I didn't see it, Uffe> and it's also marked as "not for public use" btw) Uffe> I decided to do this since the dictionary generates read/write Uffe> activity inside the transaction; if it would use Uffe> mnesia:read/1 and mnesia:write/1, it would create a loop (they are Uffe> forwarded back again to the dictionary for verification.) Uffe> It would have been possible to work around it, but this felt like Uffe> the most elegant solution. Uffe> Uffe> - mnesia_schema:schema_transaction/1 and Uffe> mnesia_schema:do_write_table_property/2 Uffe> This could perhaps have been avoided if I'd realised that there Uffe> was a 'user_properties' option for create_table/2. Uffe> Uffe> If I figure out a way to rewrite this cleanly to use only the official Uffe> API, I will of course do that. Uffe> Uffe> BTW, I would like to be able to specify commit() and rollback() hooks in Uffe> the access module as well. I can imagine that such hooks would be Uffe> dangerous, but it would allow me to write safe triggers inside the Uffe> transaction. Currently, I have to wait until after commit/rollback and Uffe> do a post_update trigger - not atomic. I have thought about introducing some kind of trigger to be executed at the end of transactions. But it is not so straightforward to do. The first issue to think about is for what purpose what you want to use a trigger. For the purpose of implementing integrity constraints it would be useful to a have a verfication trigger which should be run in the same context as the transaction, i.e. in the same process with full access to the transaction store. The transaction store access could either be indirect like lists:foldl/2 or explicit like ets:first/1 and ets:next/2. If the verification trigger is allowed to update the transaction store, the iteration order must not be affected by the updates. Such updates would of course be protected by the enclosing transaction as if they were performed in the transaction fun. Like the current mnesia_access callback interface, a verification trigger mechanism would not be able to verify integrity constraints for updates performed via the mnesia:dirty_*-functions. The verification trigger could either be run for all transactions regardless of their nesting level or only for the outermost transaction. But since you mentioned that you wanted a rollback hook, I assume that its not only integrity constraints you are interested in. What whould you use a rollback hook for? debugging? supervision? health diagnostics? If the purpose instead is notification there already exists an fairly reliable subscription mechanism in Mnesia that could be used. Introducing a commit trigger (to be run in the coordinator process) for the purpose of notification is not an especially good idea, since it is almost impossible to safe guarantee delivery of notifications if the transaction coordinator process dies during commit. The participant processes on other nodes may decide to fullfill the commit of the transaction even if the coordinator is dead. If this is the case, a commit trigger run in the coordinator process would not be able to deliver its notifications. Mnesia's subscription mechanism is designed to take care of this situation. As long as there is an active replica of the updated table, the notification will be delivered to its subscribers. /H?kan From ulf.wiger@REDACTED Thu Jan 14 14:03:41 1999 From: ulf.wiger@REDACTED (Ulf Wiger) Date: Thu, 14 Jan 1999 14:03:41 +0100 Subject: [Fwd: rdbms-1.0 user contribution] References: Message-ID: <369DEB2D.565345B5@etxb.ericsson.se> Hakan Mattsson wrote: > > On Thu, 14 Jan 1999, Ulf Wiger wrote: > > Uffe> BTW, I would like to be able to specify commit() and rollback() hooks in > Uffe> the access module as well. I can imagine that such hooks would be > Uffe> dangerous, but it would allow me to write safe triggers inside the > Uffe> transaction. Currently, I have to wait until after commit/rollback and > Uffe> do a post_update trigger - not atomic. > > I have thought about introducing some kind of trigger to be executed > at the end of transactions. But it is not so straightforward to do. > > The first issue to think about is for what purpose what you want to > use a trigger. I was too embarassed to tell. ;) > For the purpose of implementing integrity constraints it would be > useful to a have a verfication trigger which should be run in the same > context as the transaction, i.e. in the same process with full access > to the transaction store. The transaction store access could either be > indirect like lists:foldl/2 or explicit like ets:first/1 and > ets:next/2. If the verification trigger is allowed to update the > transaction store, the iteration order must not be affected by the > updates. Such updates would of course be protected by the enclosing > transaction as if they were performed in the transaction fun. Like > the current mnesia_access callback interface, a verification trigger > mechanism would not be able to verify integrity constraints for > updates performed via the mnesia:dirty_*-functions. The verification > trigger could either be run for all transactions regardless of their > nesting level or only for the outermost transaction. The verification triggers seem to work just fine. > > But since you mentioned that you wanted a rollback hook, I assume that > its not only integrity constraints you are interested in. What whould you > use a rollback hook for? debugging? supervision? health diagnostics? The first use was this (I'm not saying it's a great idea): I allow the definition of read() write() and delete() hooks, which means that you can use mnesia:read(), write() and delete() on objects which do not correspond to mnesia tables - instead, the corresponding hook function is called instead. Obviously, these functions would have side-effects, so it's important to know whether the transaction succeeds or fails. For this purpose, I have written the functions register:commit_action/1 and register_rollback_action/1, which are called after commit or rollback. Naturally, the hook functions must be prepared to be called several times during one transaction, since the transaction may be restarted. I also had in mind to provide different kinds of index (e.g. index on derived or compound attributes.) /Uffe -- Ulf Wiger, Chief Designer AXD 301 Ericsson Telecom AB tfn: +46 8 719 81 95 Varuv?gen 9, ?lvsj? mob: +46 70 519 81 95 S-126 25 Stockholm, Sweden fax: +46 8 719 43 44 From hakan@REDACTED Thu Jan 14 15:44:03 1999 From: hakan@REDACTED (Hakan Mattsson) Date: Thu, 14 Jan 1999 15:44:03 +0100 (MET) Subject: [Fwd: rdbms-1.0 user contribution] In-Reply-To: <369DEB2D.565345B5@etxb.ericsson.se> Message-ID: On Thu, 14 Jan 1999, Ulf Wiger wrote: Uffe> > But since you mentioned that you wanted a rollback hook, I assume that Uffe> > its not only integrity constraints you are interested in. What whould you Uffe> > use a rollback hook for? debugging? supervision? health diagnostics? Uffe> Uffe> The first use was this (I'm not saying it's a great idea): Uffe> Uffe> I allow the definition of read() write() and delete() hooks, which means Uffe> that you can use mnesia:read(), write() and delete() on objects which do Uffe> not correspond to mnesia tables - instead, the corresponding hook Uffe> function is called instead. Obviously, these functions would have Uffe> side-effects, so it's important to know whether the transaction succeeds Uffe> or fails. For this purpose, I have written the functions Uffe> register:commit_action/1 and register_rollback_action/1, which are Uffe> called after commit or rollback. Uffe> Uffe> Naturally, the hook functions must be prepared to be called several Uffe> times during one transaction, since the transaction may be restarted. In my first implementation of the mnesia_access callback interface, I had the notion of virtual transactions. With hooks for start, verification, commit and abort of activities. Sorry Uffe. /H?kan From icimjs@REDACTED Mon Jan 18 03:36:19 1999 From: icimjs@REDACTED (Elan) Date: Sun, 17 Jan 1999 18:36:19 -0800 Subject: vector and matrix calculations Message-ID: <3.0.5.32.19990117183619.00890860@pop.loop.com> Hi, I'm brandnew to Erlang, which I'm kind of getting to like. It's sure fast. Haven't been able to find any info on vector/matrix library. Certainly, something like that exists? Where is it documented. TIA, Elan From tobbe@REDACTED Mon Jan 18 04:49:24 1999 From: tobbe@REDACTED (Torbjorn Tornkvist) Date: Mon, 18 Jan 1999 14:49:24 +1100 Subject: vector and matrix calculations In-Reply-To: <3.0.5.32.19990117183619.00890860@pop.loop.com> References: <3.0.5.32.19990117183619.00890860@pop.loop.com> Message-ID: <199901180349.OAA25030@universe.serc.rmit.edu.au> > Haven't been able to find any info on vector/matrix library. Certainly, > something like that exists? Where is it documented. I don't think there is one (not public anyway). So you have full freedom to implement one yourself... ;-) /Tobbe (Ps. I found something very simple I did for graphic transformations years ago: http://www.serc.rmit.edu.au/~tobbe/matrix44.erl ) From icimjs@REDACTED Thu Jan 21 19:55:10 1999 From: icimjs@REDACTED (Elan) Date: Thu, 21 Jan 1999 10:55:10 -0800 Subject: Erlang FreeBSD Message-ID: <3.0.5.32.19990121105510.01529640@pop.loop.com> Hi, has anyone compiled Erlang for FreeBSD? I noticed that running ./configure resulted in an error message because the default configuration of FreeBSD uses its own make rather then gnu's make. Haven't gotten beyond compiling and installing gnu make yet. -Any other gotcha's to watch out for? - Does anyone have binary of Erlang for FreeBSD available for download somewhere? - Does anyone have experience with running Erlang as an HTTP server (using the INETS library) - on FreeBSD? TIA Elan From Ruslan@REDACTED Thu Jan 21 20:05:46 1999 From: Ruslan@REDACTED (Ruslan Shevchenko) Date: Thu, 21 Jan 1999 21:05:46 +0200 Subject: Erlang FreeBSD References: <3.0.5.32.19990121105510.01529640@pop.loop.com> Message-ID: <36A77A8A.3C1D59BC@Shevchenko.Kiev.UA> Elan wrote: > Hi, > > has anyone compiled Erlang for FreeBSD? > get erlang port from FreeBSD ports collection > > I noticed that running ./configure resulted in an error message because the > default configuration of FreeBSD uses its own make rather then gnu's make. > Haven't gotten beyond compiling and installing gnu make yet. > > -Any other gotcha's to watch out for? > - Does anyone have binary of Erlang for FreeBSD available for download > somewhere? I can put binary package somewhere, but better is cvsup current FreeBSD port tree. after this, the installation of erlang of FreeBSD is simple: cd /usr/ports/lang/erlang make make install > > - Does anyone have experience with running Erlang as an HTTP server (using > the INETS library) - on FreeBSD? > > TIA > > Elan From icimjs@REDACTED Fri Jan 22 07:21:20 1999 From: icimjs@REDACTED (Elan) Date: Thu, 21 Jan 1999 22:21:20 -0800 Subject: Thnx & Mnesia for Win95? Message-ID: <3.0.5.32.19990121222120.0091e550@pop.loop.com> Hi, first of all, thanx to Ruslan Shevchenko for alerting me to the availability of Erlang in FreeBSD ports. Is the distributed Database Management Mnesia supported and available for the MS Windows port of Erlang? Where can I find it? TIA Elan From mattias@REDACTED Fri Jan 22 10:10:52 1999 From: mattias@REDACTED (Mattias Nilsson) Date: Fri, 22 Jan 1999 10:10:52 +0100 Subject: Thnx & Mnesia for Win95? References: <3.0.5.32.19990121222120.0091e550@pop.loop.com> Message-ID: <36A8409C.EF550F20@erix.ericsson.se> Elan wrote: > > Hi, > > first of all, thanx to Ruslan Shevchenko for alerting me to the > availability of Erlang in FreeBSD ports. > > Is the distributed Database Management Mnesia supported and available for > the MS Windows port of Erlang? Where can I find it? As Mnesia is written completely in Erlang, you only need the mnesia-lib tar ball available at the Erlang.org website (and the Windows port of Erlang, ofcourse). -- Best Regards, Mattias Nilsson Ericsson Telecom AB, OTP & Applied Research From crd@REDACTED Fri Jan 22 15:12:59 1999 From: crd@REDACTED (Craig Dickson) Date: Fri, 22 Jan 1999 06:12:59 -0800 Subject: Performance of length and spawn Message-ID: <02ad01be4611$536ea0e0$6e02a8c0@crd.int2.inversenet.com> A couple of questions: Is the performance of length/1 O(1) or O(n)? (I.e. is a count of the number of items in the list stored, or is the length determined by walking the list every time?) When spawning a new process, is it necessary to duplicate in memory every argument passed to it? The specific case is that I'm writing a server that spawns new processes to handle most of the requests sent to it, in the hopes of maximizing the server's availability to accept requests. If a request basically amounts to "How long is a certain list?", then I can see a few possibilities: (1) If length/1 is O(n) and lists don't have to be copied for spawn/3: the list might be quite long, so perhaps it's worthwhile to spawn a process to get the length and send it back to the caller. (2) If length/1 is O(1): it probably is fast enough that it isn't worth the trouble to use spawn/3 even if copying would not be necessary. (3) If arguments have to be copied for spawn/3: since copying a list probably takes longer than counting its elements, spawn is probably taking more of the server's time than just calling length/1 directly. Another question: Is there any intention to add features to Erlang's module system, such as the ability to make certain modules private to others? In practice, I suppose just not documenting certain modules (or documenting them as not for public use) is enough to keep people out of them, but I'd like for the language itself to understand that some modules are for internal use only within a definable group of modules. I seem to recall that Java's "package" concept supplies such a capability (then again, I haven't done any Java in a couple of years). Thanks! Craig From ulf.wiger@REDACTED Fri Jan 22 15:49:11 1999 From: ulf.wiger@REDACTED (Ulf Wiger) Date: Fri, 22 Jan 1999 15:49:11 +0100 Subject: Performance of length and spawn References: <02ad01be4611$536ea0e0$6e02a8c0@crd.int2.inversenet.com> Message-ID: <36A88FE7.4BC3FF41@etxb.ericsson.se> Craig Dickson wrote: > > A couple of questions: > > Is the performance of length/1 O(1) or O(n)? (I.e. is a count of the number > of items in the list stored, or is the length determined by walking the list > every time?) O(n). A colleague of mine performed some measurements a while back. This is what he found on a particular version of the runtime system: CPUtime length(List) 22 1 25 3 33 5 36 7 > > When spawning a new process, is it necessary to duplicate in memory every > argument passed to it? I would think yes, but the operation is fast since it performs some kind of block copy. > The specific case is that I'm writing a server that spawns new processes to > handle most of the requests sent to it, in the hopes of maximizing the > server's availability to accept requests. If a request basically amounts to > "How long is a certain list?", then I can see a few possibilities: > > (1) If length/1 is O(n) and lists don't have to be copied for spawn/3: the > list might be quite long, so perhaps it's worthwhile to spawn a process to > get the length and send it back to the caller. > > (2) If length/1 is O(1): it probably is fast enough that it isn't worth the > trouble to use spawn/3 even if copying would not be necessary. A spawn operation without copying is fast, but spawn does copy the arguments. As it turns out, it's cheaper to find out the length of the list, than to spawn a process to do it. -module(test). % to find out how much it costs to spawn a thread -export([incr/1]). -export([incr1/2]). incr(A) -> Pid = spawn(?MODULE,incr1,[self(),A]), receive {Pid,B} -> B end. incr1(Pid,A) -> Pid ! {self(),A+1}. Eshell V4.7.3.3 (abort with ^G) 1> c(test). {ok,test} 2> timer:tc(test,incr,[17]). {60,18} 3> timer:tc(test,incr,[17]). {42,18} 4> timer:tc(test,incr,[17]). {44,18} 5> timer:tc(test,incr,[17]). {42,18} The time is given in microseconds. Thus, it takes about 45 us on my machine to spawn a process and wait for its reply (I know, it's not exactly what you were talking about.) > (3) If arguments have to be copied for spawn/3: since copying a list > probably takes longer than counting its elements, spawn is probably taking > more of the server's time than just calling length/1 directly. 8> L = lists:seq(1,10000). [...] 9> timer:tc(erlang,spawn,[erlang,length,[L]]). {2720,<0.47.0>} 10> timer:tc(erlang,spawn,[erlang,length,[L]]). {2532,<0.49.0>} 11> timer:tc(erlang,spawn,[erlang,length,[L]]). {2600,<0.51.0>} 12> timer:tc(erlang,spawn,[erlang,length,[L]]). {2471,<0.53.0>} 13> timer:tc(erlang,spawn,[erlang,length,[L]]). {2634,<0.55.0>} 14> timer:tc(erlang,length,[L]). {677,10000} 15> timer:tc(erlang,length,[L]). {571,10000} 16> timer:tc(erlang,length,[L]). {639,10000} As you can see, it's much cheaper to call length(L) (ca 600 us) than to spawn a process which handles length(L) (2.5 ms), when operating on a list of 10,000 integers. Here's a wild thought: If your input comes from outside Erlang, you may receive it as a binary (if it's text data). It is very cheap (O(1)) to find out the size of a binary. It is also cheap to pass it to another process, since the data is not copied. 19> L = lists:duplicate(10000,79). [...] 20> timer:tc(erlang,list_to_binary,[L]). {1714,#Bin} 21> timer:tc(erlang,list_to_binary,[L]). {1663,#Bin} 22> timer:tc(erlang,list_to_binary,[L]). {1718,#Bin} 23> timer:tc(erlang,list_to_binary,[L]). {1671,#Bin} 24> B = element(2,v(23)). #Bin 25> timer:tc(erlang,size,[B]). {24,10000} 26> timer:tc(erlang,size,[B]). {21,10000} 27> timer:tc(erlang,size,[B]). {21,10000} 28> timer:tc(erlang,size,[B]). {21,10000} 29> timer:tc(erlang,spawn,[erlang,size,[B]]). {43,<0.72.0>} 30> timer:tc(erlang,spawn,[erlang,size,[B]]). {40,<0.74.0>} 31> timer:tc(erlang,spawn,[erlang,size,[B]]). {38,<0.76.0>} 32> timer:tc(erlang,spawn,[erlang,size,[B]]). {40,<0.78.0>} That is, if you don't have to convert it to a binary, finding out the number of bytes is fast. > > Another question: Is there any intention to add features to Erlang's module > system, such as the ability to make certain modules private to others? In > practice, I suppose just not documenting certain modules (or documenting > them as not for public use) is enough to keep people out of them, but I'd > like for the language itself to understand that some modules are for > internal use only within a definable group of modules. I seem to recall that > Java's "package" concept supplies such a capability (then again, I haven't > done any Java in a couple of years). There is work being done. "Safe Erlang" comes to mind. http://www.erlang.se/onlinenews/archive/Erlang-OTP-news/sep98/a2.shtml /Uffe -- Ulf Wiger, Chief Designer AXD 301 Ericsson Telecom AB tfn: +46 8 719 81 95 Varuv?gen 9, ?lvsj? mob: +46 70 519 81 95 S-126 25 Stockholm, Sweden fax: +46 8 719 43 44 From joe@REDACTED Tue Jan 26 08:53:11 1999 From: joe@REDACTED (Joe Armstrong) Date: Tue, 26 Jan 1999 08:53:11 +0100 (MET) Subject: Performance of length and spawn In-Reply-To: <02ad01be4611$536ea0e0$6e02a8c0@crd.int2.inversenet.com> Message-ID: On Fri, 22 Jan 1999, Craig Dickson wrote: > A couple of questions: > > Is the performance of length/1 O(1) or O(n)? (I.e. is a count of the number > of items in the list stored, or is the length determined by walking the list > every time?) > O(n) > When spawning a new process, is it necessary to duplicate in memory every > argument passed to it? All arguments are copied. > > The specific case is that I'm writing a server that spawns new processes to > handle most of the requests sent to it, in the hopes of maximizing the > server's availability to accept requests. If a request basically amounts to > "How long is a certain list?", then I can see a few possibilities: > > (1) If length/1 is O(n) and lists don't have to be copied for spawn/3: the > list might be quite long, so perhaps it's worthwhile to spawn a process to > get the length and send it back to the caller. > > (2) If length/1 is O(1): it probably is fast enough that it isn't worth the > trouble to use spawn/3 even if copying would not be necessary. > > (3) If arguments have to be copied for spawn/3: since copying a list > probably takes longer than counting its elements, spawn is probably taking > more of the server's time than just calling length/1 directly. > If the lists are short then I wouldn't bother with any optimisations. I can't define short - but I wouldn't be looking at any optimisations if I was thinking in terms of say less than 5,000 elements. If the lists get big then I'd use a data structure called a binary. Binaries are untyped chunks of memory. They are not copied between processes on the same node (they are reference counted). For messages: The bif size(Binary) is O(1) If my data structure were say 100,000 element then I'd certainly use binaries. Somewhere between 5,000 and 100,000 elements I'd change representation from lists to binaries. (Hopefully I'd have written the program in such a way that the choice of representation would now impact the code much). I don't know what your problem is but usually a major source of inefficiency is getting data from the outside world into Erlang, here you should almost always use binaries - the break even point comes with very short lists (i.e. even with a few hundred elements you get a significant gain using binaries instead of lists). > Another question: Is there any intention to add > features to Erlang's module system, such as the ability to make > certain modules private to others? In practice, I suppose just not > documenting certain modules (or documenting them as not for public > use) is enough to keep people out of them, but I'd like for the > language itself to understand that some modules are for internal use > only within a definable group of modules. Not yet planned. Sorry. I usually make one main module with all the public exports and a lot of sub modules. This is the convention that is used in the system. Example: The main module snmp.erl offers the public interface to the snmp package. All internal modules are given names like snmp_XXX.erl Hope that helps /Joe -- Joe Armstrong Computer Science Laboratory +46 8 719 9452 AT2/ETX/DN/SU Ericsson Telecom SE-126 25 Stockholm Sweden joe@REDACTED http://www.ericsson.se/cslab/~joe From pearcs@REDACTED Wed Jan 27 20:24:12 1999 From: pearcs@REDACTED (Shawn Pearce) Date: Wed, 27 Jan 1999 14:24:12 -0500 (EST) Subject: Question about fun's Message-ID: Ok, we're looking at implementing a system in Erlang where it would be nice to have true object-oriented behavior. The way this is typically done in scheme is to make each object a lambda and bind the object state to the lambda when you construct the object. Thus you can do "(object print)" to make it print out stuff. I'm thinking that we'd do something similar in Erlang like so: -module(myclass). -export([new/0]). new() -> save_state([]). save_state(State) -> fun(Message) -> myclass:dispatch(State,Message) end. dispatch(State,{print}) -> io:format("Hi!"); dispatch(State,{append,Item}) -> save_state([Item|State]); dispatch(State,{get}) -> State; dispatch(State,{empty}) -> save_state([]). Then I can work with the object like this: O=myclass:new(). O1=O({append,TheThingy}). O1({print}). O2=O1({empty}). What are the drawbacks, ie is the fun going to cost me a large amount of RAM, or a large amount of processing overhead on each message? -- Shawn. (The above are the rantings of a body without a mind.) From ulf.wiger@REDACTED Wed Jan 27 21:23:38 1999 From: ulf.wiger@REDACTED (Ulf Wiger) Date: Wed, 27 Jan 1999 21:23:38 +0100 Subject: Question about fun's References: Message-ID: <36AF75CA.F110B877@etxb.ericsson.se> Shawn Pearce wrote: > > Ok, we're looking at implementing a system in Erlang where it would be nice to > have true object-oriented behavior. The way this is typically done in scheme > is to make each object a lambda and bind the object state to the lambda when > you construct the object. Thus you can do "(object print)" to make it print > out stuff. > > I'm thinking that we'd do something similar in Erlang like so: > > -module(myclass). > -export([new/0]). > > new() -> save_state([]). > > save_state(State) -> > fun(Message) -> > myclass:dispatch(State,Message) > end. > > dispatch(State,{print}) -> io:format("Hi!"); > dispatch(State,{append,Item}) -> save_state([Item|State]); > dispatch(State,{get}) -> State; > dispatch(State,{empty}) -> save_state([]). > > Then I can work with the object like this: > > O=myclass:new(). > O1=O({append,TheThingy}). > O1({print}). > O2=O1({empty}). Personally, I'd go with 'print' and 'empty' instead of tuples with only one element. You don't have a type checker that's gonna complain - Erlang really couldn't care less, but your match operation speeds up somewhat. A matter of preference, I guess. > > What are the drawbacks, ie is the fun going to cost me a large amount of RAM, > or a large amount of processing overhead on each message? Funs don't cost much in terms of memory. You can look at how a fun is represented: -module(myclass). -export([new/0]). new() -> F = save_state([]), tuple_to_list(F). %% hack to reveal the representation of a fun save_state(State) -> fun(Message) -> myclass:dispatch(State,Message) end. If you compile and run: 1> myclass:new(). ['fun',myclass,0,7662692,{[]}] That is, a 5-tuple. The rest is compiled and represented as one instance. The processing overhead is roughly the same as for apply/3. A few microseconds per call. On the minus side: In the current JAM implementation, error reporting for funs is lousy and code change on-the-fly doesn't work well (the fun's internal reference changes and the fun instance has to be recreated.) Apart from this, I have found that it's most often counter-productive to use an object-oriented style of programming in Erlang. Personally, I spent my first 6 months with Erlang trying to make it object-oriented. After that, I had convinced myself that you get further by using Erlang as it was intended (granted, we didn't have funs in those days...) You could do a similar thing without funs, to begin with: -module(myclass). -export([new/0, dispatch/2]). new() -> []. dispatch(State, print) -> io:format("~p~n", [State]); dispatch(State, {append,Item}) -> State ++ Item; dispatch(State, get) -> State; dispatch(State, empty) -> []. then: O = myclass:new(). O1 = myclass:dispatch(O, {append,TheThingy}). etc: You may argue that the object-oriented aspect got lost: -module(myclass). -export([new/0, dispatch/2]). new() -> {?MODULE, []}. dispatch(State, print) -> io:format("~p~n", [State]); dispatch(State, {append,Item}) -> State ++ Item; dispatch(State, get) -> State; dispatch(State, empty) -> []. -module(oo). -export([msg/2]). msg({Class, State}, Msg) -> Class:dispatch(State, Msg). %% this uses apply/3 instead of funs then: O = myclass:new(). O1 = oo:msg(O, {append,TheThingy}). O2 = oo:msg(O1, print). ... Useless exercise? Perhaps. What you gain is that you avoid the negative aspects (bugs?) of funs, at little syntactical expense. I have written code like that. Sometimes, I find it justified (when the OO paradigm really adds advantages), but most of the time, it just makes the code harder to read, harder to write, and harder to maintain. So what do I propose? Look at modules like: lists (lists:append(L1, L2), lists:reverse(L), ...) queue (queue:new(), queue:in(Q, Item), queue:out(Q), ...) application (application:start(Name), application:stop(Name), ...) and so on. The big advantage of this style of programming is that programs become much easier to read, since the semantics are obvious. You still get a great deal of reuse, and your productivity will be very high. I admit I haven't the faintest idea of what kind of program you're trying to write. Perhaps your problem domain really calls for object-oriented design? If so, forgive me, but it's very common for programmers new to Erlang to go overboard trying to make everything object-oriented. /Uffe -- Ulf Wiger, Chief Designer AXD 301 Ericsson Telecom AB tfn: +46 8 719 81 95 Varuv?gen 9, ?lvsj? mob: +46 70 519 81 95 S-126 25 Stockholm, Sweden fax: +46 8 719 43 44 From pearcs@REDACTED Wed Jan 27 21:42:43 1999 From: pearcs@REDACTED (Shawn Pearce) Date: Wed, 27 Jan 1999 15:42:43 -0500 (EST) Subject: Question about fun's In-Reply-To: <36AF75CA.F110B877@etxb.ericsson.se> Message-ID: Ulf Wiger wrote: > Personally, I'd go with 'print' and 'empty' instead of tuples with only > one element. You don't have a type checker that's gonna complain - > Erlang really couldn't care less, but your match operation speeds up > somewhat. A matter of preference, I guess. > > > > > What are the drawbacks, ie is the fun going to cost me a large amount of > > RAM, or a large amount of processing overhead on each message? > > Funs don't cost much in terms of memory. You can look at how a fun is > represented: > > > -module(myclass). > -export([new/0]). > > new() -> > F = save_state([]), > tuple_to_list(F). %% hack to reveal the representation of a fun > > save_state(State) -> > fun(Message) -> > myclass:dispatch(State,Message) > end. > > If you compile and run: > > 1> myclass:new(). > ['fun',myclass,0,7662692,{[]}] > > That is, a 5-tuple. The rest is compiled and represented as one > instance. > > The processing overhead is roughly the same as for apply/3. A few > microseconds per call. > > On the minus side: > In the current JAM implementation, error reporting for funs is lousy and > code change on-the-fly doesn't work well (the fun's internal reference > changes and the fun instance has to be recreated.) > > Apart from this, I have found that it's most often counter-productive to > use an object-oriented style of programming in Erlang. Personally, I > spent my first 6 months with Erlang trying to make it object-oriented. > After that, I had convinced myself that you get further by using Erlang > as it was intended (granted, we didn't have funs in those days...) > > You could do a similar thing without funs, to begin with: > > -module(myclass). > -export([new/0, > dispatch/2]). > > new() -> []. > > dispatch(State, print) -> io:format("~p~n", [State]); > dispatch(State, {append,Item}) -> State ++ Item; > dispatch(State, get) -> State; > dispatch(State, empty) -> []. > > then: > > O = myclass:new(). > O1 = myclass:dispatch(O, {append,TheThingy}). > > etc: > > You may argue that the object-oriented aspect got lost: > > -module(myclass). > -export([new/0, > dispatch/2]). > > > new() -> > {?MODULE, []}. > > dispatch(State, print) -> io:format("~p~n", [State]); > dispatch(State, {append,Item}) -> State ++ Item; > dispatch(State, get) -> State; > dispatch(State, empty) -> []. > > -module(oo). > -export([msg/2]). > > msg({Class, State}, Msg) -> > Class:dispatch(State, Msg). %% this uses apply/3 instead of funs > > then: > > O = myclass:new(). > O1 = oo:msg(O, {append,TheThingy}). > O2 = oo:msg(O1, print). > ... > > > Useless exercise? > > Perhaps. What you gain is that you avoid the negative aspects (bugs?) of > funs, at little syntactical expense. I have written code like that. > Sometimes, I find it justified (when the OO paradigm really adds > advantages), but most of the time, it just makes the code harder to > read, harder to write, and harder to maintain. > > So what do I propose? > > Look at modules like: > > lists (lists:append(L1, L2), lists:reverse(L), ...) > queue (queue:new(), queue:in(Q, Item), queue:out(Q), ...) > application (application:start(Name), application:stop(Name), ...) > > and so on. The big advantage of this style of programming is that > programs become much easier to read, since the semantics are obvious. > You still get a great deal of reuse, and your productivity will be very > high. > > I admit I haven't the faintest idea of what kind of program you're > trying to write. Perhaps your problem domain really calls for > object-oriented design? > > If so, forgive me, but it's very common for programmers new to Erlang to > go overboard trying to make everything object-oriented. I'm one of the authors of the Casbah Project, an open source project, (http://www.ntlug.org/casbah/). Our entire system is very much object oriented based, and has its "server" currently written in Java. We are looking at also implementing our server in Erlang, for obvious reasons. The server is a very "pluggable" architecture, but its all object-oriented based. A language like Objective-C would be ideal for building our server, as it is very dynamic in its object-dispatch mechanism, etc. Essentially parts of the system will need to invoke code on some plugin module whose name isn't known until runtime, and even then will change on invoctions. I know that pretty much breaks erlang's ideas, but not that much: because if we pass in the same arguments, we'll still expect it to always return the same result, it will just alter its behavior based on that input. So if we pass in an item of class NatrounFS, it should do a, if its of class NatrounSQL, it needs to execute code b. I didn't realize that the code example you showed above would work, and doh! I should have thought about using oo:msg() to wrap around apply/3 rather than using a fun. We'll implement each class in its own module, but we really sort of need the ability to have methods dispatched based on the class at runtime, rather than at the time of the coding. Thanks for the suggestions! -- Shawn. (The above are the rantings of a body without a mind.) From mbjk@REDACTED Wed Jan 27 22:08:33 1999 From: mbjk@REDACTED (Martin Bjorklund) Date: Wed, 27 Jan 1999 16:08:33 -0500 Subject: Question about fun's In-Reply-To: Your message of "Wed, 27 Jan 1999 15:42:43 -0500 (EST)" References: Message-ID: <19990127160833F.mbjk@eecs.umich.edu> Shawn Pearce wrote: > Essentially parts of the system will need to invoke code on some > plugin module whose name isn't known until runtime, and even then > will change on invoctions. This is a pretty common situation in generic Erlang programs - use a callback module (which may change dynamically) and call a certain function in that module at certain occasions. One example is the module gen_server, which implements a generic server process. The server is given the name of a callback module when the process is started. For each request the server receives, a function in the callback module is called: -module(gs). start(Mod) -> spawn(gs, init, [Mod]). init(Mod) -> InitState = Mod:init(), loop(Mod, InitState). loop(Mod, State) -> receive {request, From, Req} -> {Reply, NewState} = Mod:handle_request(Req, State), From ! Reply, loop(Mod, NewState); {change_module, NewMod} -> loop(NewMod, NewState) end. -module(callback1). init() -> []; handle_request({append, Item}, State) -> {ok, State ++ Item}; handle_request(print, State) -> io:format("~p", [State]), {ok, State}. etc. > We'll implement each class in its own module, but we really sort of need the > ability to have methods dispatched based on the class at runtime, rather than > at the time of the coding. Mod:handle_request(Mod) is an example of that. It is just a syntactic sugar for apply(Mod, handle_request, [Mod]). Also, the function name could be dynamic: Mod:Fun(...) works just fine. /martin From joe@REDACTED Thu Jan 28 10:51:51 1999 From: joe@REDACTED (Joe Armstrong) Date: Thu, 28 Jan 1999 10:51:51 +0100 (MET) Subject: Question about fun's In-Reply-To: Message-ID: Hi Shawn, let me comment on your program line by line ... > Ok, we're looking at implementing a system in Erlang where it would be nice to > have true object-oriented behavior. The way this is typically done in scheme > is to make each object a lambda and bind the object state to the lambda when > you construct the object. Thus you can do "(object print)" to make it print > out stuff. > > I'm thinking that we'd do something similar in Erlang like so: > > -module(myclass). > -export([new/0]). > > new() -> save_state([]). > > save_state(State) -> > fun(Message) -> > myclass:dispatch(State,Message) Better might be: ?MODULE:dispatch(State, Message) ?MODULE is a pre-defined macro whoes value is the current module If you do it this way and decide to change the name of the module then the program will still work! If you bake the name in and at a later state decide to change the module name (which I'm always doing), you'll probably forget to change the call > end. > > dispatch(State,{print}) -> io:format("Hi!"); > dispatch(State,{append,Item}) -> save_state([Item|State]); > dispatch(State,{get}) -> State; > dispatch(State,{empty}) -> save_state([]). > OOOps - Erlang is dynamically typed. But you should always "think types" > dispatch(State,{print}) -> io:format("Hi!"); The return value is the atom ok > dispatch(State,{append,Item}) -> save_state([Item|State]); The return value is a Fun > dispatch(State,{get}) -> State; The return value is a list of Items > dispatch(State,{empty}) -> save_state([]). The Return value is a Fun. Code like this might one day bite you in the tail. Also why use {get}, {print} etc. {..} is a tuple construtor This is like building a C struct and putting ONE value in it. C structs and Erlang tuples are designed as holders for multiple values, not singletons. So always use X instead of {X}. > Then I can work with the object like this: > > O=myclass:new(). > O1=O({append,TheThingy}). > O1({print}). > O2=O1({empty}). > > What are the drawbacks, ie is the fun going to cost me a large amount of RAM, > or a large amount of processing overhead on each message? > No. Funs involve very small overhead but they do make the program shorter and easier to read. Before hacking yourself to death I'd read the "design principles" section in the on-line documentation. This is in: http://www.erlang.org/doc/doc/design_principles/part_frame.html Or wherever you've installed it locally. (I'd recommend you take the *entire* documentation and install it locally) This tells how to set up a client/server in the "Erlang way" which is not OO :-) [BTW In making a system the tricky bit is concurrency/load balancing/ fault-tolerence/fail-over etc.] The generic methods in the OTP libraries do the tricky bits. All you have to do is plug in the "semantics". These are small functions, like: Fun(State, Request} -> {reply, State', Reply} Then you get the tricky bits for free. If you do the small functions in an OO style then you should make sure that match up with the OTP libraries so you get the fault-tolerence for free. /Joe -- Joe Armstrong Computer Science Laboratory +46 8 719 9452 AT2/ETX/DN/SU Ericsson Telecom SE-126 25 Stockholm Sweden joe@REDACTED http://www.ericsson.se/cslab/~joe