From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,16bd8131a17b875d,start X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news1.google.com!news2.google.com!news.maxwell.syr.edu!border1.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!nntp.giganews.com!cyclone1.gnilink.net!spamkiller2.gnilink.net!gnilink.net!trndny06.POSTED!0f19ed38!not-for-mail From: "Frank J. Lhota" Reply-To: NOSPAM.lhota@adarose.com User-Agent: Mozilla Thunderbird 1.0.2 (Windows/20050317) X-Accept-Language: en-us, en MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Virtual Components in Ada and Ruby Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Message-ID: <2ifue.819$Z97.597@trndny06> Date: Wed, 22 Jun 2005 15:17:18 GMT NNTP-Posting-Host: 151.203.15.19 X-Complaints-To: abuse@verizon.net X-Trace: trndny06 1119453438 151.203.15.19 (Wed, 22 Jun 2005 11:17:18 EDT) NNTP-Posting-Date: Wed, 22 Jun 2005 11:17:18 EDT Xref: g2news1.google.com comp.lang.ada:11565 Date: 2005-06-22T15:17:18+00:00 List-Id: Recently I was studying the Ruby scripting language. One of the features of the Ruby language has a parallel in Ada. A Ruby class has one or more "attributes", which are used to read or manipulate the data in an object. A Ruby attribute is readable if it can be used to read a value associated with an object. The book "Programming Ruby" uses the example of a class Song, used to represent a song that included in a Jukebox. A readable attribute of the Song class might be durationInSeconds. If thisSong is an instance of Song class, a Ruby programmer could write a statement like this to increment totalDuration by the duration of thisSong: totalDuration += thisSong.durationInSeconds Conversely, a Ruby attribute is writable if it can be assigned a value. If the durationInSeconds attribute of the Song class is writable, we could write a statement such as this thisSong.durationInSeconds = 190 Ruby attributes look like record components, and many Ruby attributes are in fact implemented using instance variables (the Ruby equivalent of Ada record components). But Ruby also support virtual attributes, that is, attributes that do not correspond to any actual instance variable. Instead, a virtual attribute provides methods for reading and / or writing that attribute. To illustrate, let us go back to our Song example. This class has the durationInSeconds attribute, implemented as an instance variable. Assume that in some programs, it is more useful to work with a song's duration in minutes. We therefore would like to have a readable / writable attribute called durationInMinutes. Obviously, it would not be desirable to implement the durationInMinutes attribute with another instance variable, since we would then have two instance variables that must always be updated in tandem. A better approach would be to implement durationInMinutes as follows: class Song # Read the virtual attribute durationInMinutes def durationInMinutes @durationInSeconds/60.0 end # Write the virtual attribute durationInMinutes def durationInMinutes=(value) @durationInSeconds = value*60.0 end end Basically, this approach implements reading and writing the durationInMinutes by performing the appropriate action on the durationInSeconds instance variable. Of course, whether or not an attribute is virtual is an internal implementation issue. Outside of the Song class, the durationInMinutes attribute is used exactly the same way as the durationInSeconds attribute. So what does this have to do with Ada? Well, one could argue that the notion of virtual components has existed in Ada from the very beginning. Consider a packed record, such as the following: subtype Seconds_Count is Natural range 0 .. 59; subtype Minutes_Count is Natural range 0 .. 59; ... type Timestamp is record Sec : Seconds_Count; Min : Minutes_Count; ... end record; for Timestamp use record Sec at 0 range 0 .. 5; Min at 0 range 6 .. 11; ... end record; Technically, the type of the Min component in Timestamp is Integer. But Min is not really implemented as an integer in memory. Min is shorter than an integer, and it does not even start on a byte boundary, much less meet any byte alignment requirements for an integer. Min is definitely not aliased. The Ada compiler, however, makes it look as though Min is an integer by using mask and shift procedures to read and write integer values for Min. For example, if TS is an object of type Timestamp, the Ada statement Ada.Integer_Text_Io.Put (TS.Min); is often (always?) implemented by having the compiler retrieve the integer value of TS.Min using mask and shift, then passing that integer to the "Put" procedure. Similarly, TS.Min := Some_Integer; is implemented by a mask and shirt to store Some_Integer into the bits for Min. Borrowing from the Ruby terminology, Min is a virtual component. Looking ahead to Ada 201Z, should there be user-defined virtual record components? Currently, a component of a record must always be defined as a section of memory in a record. Would it be desirable to also be able to define a record component in terms of subprograms for reading and writing that component? Last year, I had a similar proposal for virtual record components: http://groups-beta.google.com/group/comp.lang.ada/browse_thread/thread/b5ab7c96b188b59e/83840467bdfa413f?q=Lhota&rnum=2#83840467bdfa413f