Compound data type: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 415: Line 415:
One could also simply instantiate a generic object and "monkeypatch" it:
One could also simply instantiate a generic object and "monkeypatch" it:


<python>point = object()
<python>
class MyObject(object): pass
point.x, point.y = 0, 1</python>
point = MyObject()
point.x, point.y = 0, 1
# objects directly instantiated from "object()" cannot be "monkey patched"
# however this can generally be done to it's subclasses
</python>


=={{header|Ruby}}==
=={{header|Ruby}}==

Revision as of 19:36, 18 November 2008

Task
Compound data type
You are encouraged to solve this task according to the task description, using any language you may know.

Data Structure
This illustrates a data structure, a means of storing data within a program.

You may see other such structures in the Data Structures category.

Create a compound data type Point(x,y).

A compound data type is one that holds multiple independent values. See also Enumeration.

Ada

Tagged Type

Ada tagged types are extensible through inheritance. The reserved word tagged causes the compiler to create a tag for the type. The tag identifies the position of the type in an inheritance hierarchy. <ada>type Point is tagged record

  X : Integer := 0;
  Y : Integer := 0;

end record;</ada>

Record Type

Ada record types are not extensible through inheritance. Without the reserved word tagged the record does not belong to an inheritance hierarchy. <ada>type Point is record

  X : Integer := 0;
  Y : Integer := 0;

end record;</ada>

Parameterized Types

An Ada record type can contain a discriminant. The discriminant is used to choose between internal structural representations. Parameterized types were introduced to Ada before tagged types. Inheritance is generally a cleaner solution to multiple representations than is a parameterized type. <ada>type Person (Gender : Gender_Type) is record

  Name   : Name_String;
  Age    : Natural;
  Weight : Float;
  Case Gender is
     when Male =>
        Beard_Length : Float;
     when Female =>
        null;
  end case;

end record;</ada> In this case every person will have the attributes of gender, name, age, and weight. A person with a male gender will also have a beard length.

ALGOL 68

Tagged Type

ALGOL 68 has only tagged-union/discriminants. And the tagging was strictly done by the type (MODE) of the members.

MODE UNIONX = UNION(
   STRUCT(REAL r, INT i),
   INT,
   REAL,
   STRUCT(INT ii),
   STRUCT(REAL rr),
   STRUCT([]REAL r)
);

To extract the apropriate member of a UNION a conformity-clause has to be used.

UNIONX data := 6.6;
CASE data IN
   (INT i): printf(($"r: "gl$,i)),
   (REAL r): printf(($"r: "gl$,r)),
   (STRUCT(REAL r, INT i) s): printf(($"r&i: "2(g)l$,s)),
   (STRUCT([]REAL r) s): printf(($"r: "n(UPB r OF s)(g)l$,s))
OUT
  printf($"Other cases"l$)
ESAC; 

The conformity-clause does mean that ALGOL 68 avoids the need for duck typing, but it also makes the tagged-union kinda tough to use, except maybe in certain special cases.

Record Type

ALGOL 68 record types are not extensible through inheritance but they may be part of a larger STRUCT composition.

MODE POINT = STRUCT(
   INT x,
   INT y
);

Parameterized Types

An ALGOL 68 record type can contain a tagged-union/discriminant. The tagged-union/discriminant is used to choose between internal structural representations. Parametrized types were introduced to ALGOL 68 before tagged types. Inheritance is generally a cleaner solution to multiple representations than is a parametrized type.

MODE PERSON = STRUCT(
   STRING name,
   REAL age,
   REAL weight,
   UNION (
      STRUCT (REAL beard length),
      VOID
   ) gender details
);

In this case every PERSON will have the attributes of gender details, name, age, and weight. A PERSON may or may not have a beard. The sex is implied by the tagging.

BASIC

Works with: QuickBasic version 4.5
Works with: PB version 7.1
TYPE Point
  x AS INTEGER
  y AS INTEGER
END TYPE

C

Works with: GCC
Works with: MSVC
Works with: BCC
Works with: Watcom

Libraries: Standard

<c>typedef struct Point {

 int x;
 int y;

} Point;</c>

C++

<cpp>struct Point {

 int x;
 int y;

};</cpp>

It is also possible to add a constructor (this allows the use of Point(x, y) in expressions): <cpp>struct Point {

 int x;
 int y;
 Point(int ax, int ay): x(ax), y(ax) {}

};</cpp>

Point can also be parametrized on the coordinate type: <cpp>template<typename Coordinate> struct point {

 Coordinate x, y;

};

// A point with integer coordinates Point<int> point1 = { 3, 5 };

// a point with floating point coordinates Point<float> point2 = { 1.7, 3.6 };</cpp> Of course, a constructor can be added in this case as well.

C#

<csharp>struct Point {

 public int x, y;
 public Point(int x, int y) {
   this.x = x;
   this.y = y;
 }

}</csharp>

Clean

Record type

:: Point = { x :: Int, y :: Int }

Parameterized Algebraic type

:: Point a = Point a a  // usage: (Point Int)

Synonym type

:: Point :== (Int, Int)

Common Lisp

<lisp>(defstruct point x y)</lisp>

E

def makePoint(x, y) {
    def point {
        to getX() { return x }
        to getY() { return y }
    }
    return point
}

Forth

There is no standard structure syntax in Forth, but it is easy to define words for creating and accessing data structures.

: pt>x ( point -- x ) ;
: pt>y ( point -- y ) CELL+ ;
: .pt ( point -- ) dup pt>x @ . pt>y @ . ;    \ or for this simple structure, 2@ . .

create point 6 , 0 ,
7 point pt>y !
.pt    \ 6 7
Works with: GNU Forth version 0.6.2

Some Forths have mechanisms for declaring complex structures. For example, GNU Forth uses this syntax:

struct
  cell% field pt>x
  cell% field pt>y
end-struct point%

Fortran

In ISO Fortran 90 or later, use a TYPE declaration, "constructor" syntax, and field delimiter syntax:

   program typedemo
       type rational                                           ! Type declaration
           integer :: numerator
           integer :: denominator
       end type rational
       
       type( rational ), parameter :: zero = rational( 0, 1 )  ! Variables initialized by constructor syntax
       type( rational ), parameter :: one  = rational( 1, 1 )
       type( rational ), parameter :: half = rational( 1, 2 )
       integer :: n, halfd, halfn
       type( rational ) :: &
           one_over_n(20) = (/ (rational( 1, n ), n = 1, 20) /) ! Array initialized with constructor inside implied-do array initializer
       integer :: oon_denoms(20)
       
       halfd = half%denominator                                ! field access with "%" delimiter
       halfn = half%numerator
       
       oon_denoms = one_over_n%denominator                     ! Access denominator field in every rational array element
                                                               ! & store as integer array
   end program typedemo

Haskell

Algebraic Data Type

See algebraic data type. The different options ("Empty", "Leaf", "Node") are called constructors, and is associated with 0 or more arguments with the declared types.

 data Tree = Empty
           | Leaf Int
           | Node Tree Tree
 deriving (Eq, Show)
 
 t1 = Node (Leaf 1) (Node (Leaf 2) (Leaf 3))

Tagged Type

This is special case of algebraic data type above with only one constructor.

 data Point = Point Integer Integer
 instance Show Point where
     show (Point x y) = "("++(show x)++","++(show y)++")"
 p = Point 6 7

Record Type

Entries in an algebraic data type constructor can be given field names.

data Point = Point { x :: Integer, y :: Integer } 
deriving (Eq, Show)

The deriving clause here provides default instances for equality and conversion to string.

Different equivalent ways of constructing a point:

p  = Point 2 3
p' = Point { x=4, y=5 }

The field name is also a function that extracts the field value out of the record

x p' -- evaluates to 4

Tuple Type

The declared type is a type synonym.

type Point = (Int,Int)

p = (2,3)

Discriminated Type

Just an algebraic data type with multiple constructors being records

data Person =
    Male   { name :: String, age :: Integer, weight :: Double, 
             beard_length :: Double }
  | Female { name :: String, age :: Integer, weight :: Double }
  deriving (Eq, Show)

Note that the field names may be identical in alternatives.

IDL

point = {x: 6 , y: 0 } 
point.y = 7
print, point
;=> {       6       7}

Java

We use a class: <java>public class Point {

 public int x, y;
 public Point() { this(0); }
 public Point(int x0) { this(x0,0); }
 public Point(int x0, int y0) { x = x0; y = y0; }
 public static void main(String args[])
 {
   Point point = new Point(1,2);
   System.out.println("x = " + point.x );
   System.out.println("y = " + point.y );
 }

}</java>

JavaScript

<javascript>var point = new Object(); point.x = 1; point.y = 2;</javascript>

JSON

 var point = {
   x:1,
   y:2
 };

In Logo, a point is represented by a list of two numbers. For example, this will draw a triangle:

setpos [100 100] setpos [100 0] setpos [0 0]
show pos  ; [0 0]

Access is via normal list operations like FIRST and BUTFIRST (BF). X is FIRST point, Y is LAST point. For example, a simple drawing program which exits if mouse X is negative:

until [(first mousepos) < 0] [ifelse button? [pendown] [penup]  setpos mousepos]

MAXScript

Point is a built-in object type in MAX, so...

struct myPoint (x, y)
newPoint = myPoint x:3 y:4

In practice however, you'd use MAX's built in Point2 type

newPoint = Point2 3 4

OCaml

Algebraic Data Type

See algebraic data type. The different options ("Empty", "Leaf", "Node") are called constructors, and is associated with 0 or 1 arguments with the declared types; multiple arguments are handled with tuples.

<ocaml>type tree = Empty

         | Leaf of int
         | Node of tree * tree

t1 = Node (Leaf 1, Node (Leaf 2, Leaf 3))</ocaml>

Record Type

<ocaml>type point = { x : int; y : int }</ocaml>

How to construct a point:

<ocaml>let p = { x = 4; y = 5 }</ocaml>

You can use the dot (".") to access fields. <ocaml>p.x (* evaluates to 4 *)</ocaml>

Fields can be optionally declared to be mutable: <ocaml>type mutable_point = { mutable x2 : int; mutable y2 : int }</ocaml>

Then they can be assigned using the assignment operator "<-" <ocaml>let p2 = { x2 = 4; y2 = 5 } in

 p2.x2 <- 6;
 p2 (* evaluates to { x2 = 6; y2 = 5 } *)</ocaml>

Tuple Type

The declared type is a type synonym.

<ocaml>type point = int * int

let p = (2,3)</ocaml>

OpenEdge/Progress

The temp-table is a in memory database table. So you can query sort and iterate it, but is the data structure that comes closest.

 def temp-table point
   field x as int
   field y as int
   .

Another option would be a simple class.

Pascal

<pascal>type point = record

             x, y: integer;
            end;</pascal>

Perl

Works with: Perl version 5.x

This is a hash (associative array), but accomplishes the task. <perl>my %point = (

  x => 3,
  y => 8

);</perl>

PHP

<php># Using pack/unpack $point = pack("ii", 1, 2);

$u = unpack("ix/iy", $point); echo $x; echo $y;

list($x,$y) = unpack("ii", $point); echo $x; echo $y;</php>

Pop11

uses objectclass;
define :class Point;
   slot x = 0;
   slot y = 0;
enddefine;

Python

The simplest way it to use a tuple, or a list if it should be mutable: <python>X, Y = 0, 1 p = (3, 4) p = [3, 4]

print p[X]</python>

If needed, you can use class:

<python>class Point:

   def __init__(self, x=0, y=0):
       self.x = x
       self.y = y

p = Point() print p.x</python>

One could also simply instantiate a generic object and "monkeypatch" it:

<python> class MyObject(object): pass point = MyObject() point.x, point.y = 0, 1

  1. objects directly instantiated from "object()" cannot be "monkey patched"
  2. however this can generally be done to it's subclasses

</python>

Ruby

Point = Struct.new(:x,:y) p = Point.new(6,7) p.y=3 puts p => #<struct Point x=6, y=3>

Scheme

Here a cons-pair is used. For more complicated things you might use a list or vector, or some arrangement of pairs. <scheme>(define (make-point x y)

 (cons x y))

(define (point-x point)

 (car point))

(define (point-y point)

 (cdr point))</scheme>

Tcl

This appears to be a sub-functionality of a proper associative array:

 array set point {x 4 y 5}
 set point(y) 7
 puts "Point is {$point(x),$point(y)}"
 # => Point is {4,7}

XSLT

Data types in XSLT are expressed as XML nodes. Members of a node can be either attributes or child nodes. Access to data is via XPath expressions.

Attributes

Attributes are often used for simple values. This is how a point might be represented in SVG, for example.

<point x="20" y="30"/>
<!-- context is a point node. The '@' prefix selects named attributes of the current node. -->
<fo:block>Point = <xsl:value-of select="@x"/>, <xsl:value-of select="@y"/></fo:block>

Children

More complex, multivariate, and nested data structures can be represented using child nodes.

<circle>
  <point>
    <x>20</x>
    <y>30</y>
  </point>
  <radius>10</radius>
</circle>
<!-- context is a circle node. Children are accessed using a path-like notation (hence the name "XPath"). -->
<fo:block>Circle center = <xsl:value-of select="point/x"/>, <xsl:value-of select="point/y"/></fo:block>