Compound data type: Difference between revisions
m Unicon/Icon consistency 2 |
Added PicoLisp |
||
Line 548: | Line 548: | ||
$point = new Point(1, 2); |
$point = new Point(1, 2); |
||
echo $point; # will call __tostring() in later releases of PHP 5.2; before that, it won't work so good.</lang> |
echo $point; # will call __tostring() in later releases of PHP 5.2; before that, it won't work so good.</lang> |
||
=={{header|PicoLisp}}== |
|||
<lang PicoLisp>(class +Point) |
|||
(dm T (X Y) |
|||
(=: x X) |
|||
(=: y Y) ) |
|||
(setq P (new '(+Point) 3 4)) |
|||
(show P)</lang> |
|||
Output: |
|||
<pre>$52717735311266 (+Point) |
|||
y 4 |
|||
x 3</pre> |
|||
=={{header|PL/I}}== |
=={{header|PL/I}}== |
Revision as of 15:23, 23 May 2010
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.
Create a compound data type Point(x,y).
A compound data type is one that holds multiple independent values. See also Enumeration.
ActionScript
<lang actionscript>package {
public class Point { public var x:Number; public var y:Number; public function Point(x:Number, y:Number) { this.x = x; this.y = y; } }
}</lang>
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. <lang ada>type Point is tagged record
X : Integer := 0; Y : Integer := 0;
end record;</lang>
Record Type
Ada record types are not extensible through inheritance. Without the reserved word tagged the record does not belong to an inheritance hierarchy. <lang ada>type Point is record
X : Integer := 0; Y : Integer := 0;
end record;</lang>
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. <lang 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;</lang> 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. <lang algol68>MODE UNIONX = UNION(
STRUCT(REAL r, INT i), INT, REAL, STRUCT(INT ii), STRUCT(REAL rr), STRUCT([]REAL r)
);</lang> To extract the apropriate member of a UNION a conformity-clause has to be used. <lang algol68>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;</lang> 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. <lang algol68>MODE POINT = STRUCT(
INT x, INT y
);</lang>
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. <lang algol68>MODE PERSON = STRUCT(
STRING name, REAL age, REAL weight, UNION ( STRUCT (REAL beard length), VOID ) gender details
);</lang> 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.
AmigaE
<lang amigae>OBJECT point
x, y
ENDOBJECT
PROC main()
DEF pt:PTR TO point,
NEW pt pt.x := 10.4 pt.y := 3.14 END pt
ENDPROC</lang>
AWK
As usual, arrays are the only data type more complex than a number or a string. Having to use quotes around constant strings as element selectors: <lang awk>p["x"]=10 p["y"]=42</lang>
BASIC
<lang qb>TYPE Point
x AS INTEGER y AS INTEGER END TYPE</lang>
C
<lang c>typedef struct Point {
int x; int y;
} Point;</lang>
C++
<lang cpp>struct Point {
int x; int y;
};</lang>
It is also possible to add a constructor (this allows the use of Point(x, y) in expressions): <lang cpp>struct Point {
int x; int y; Point(int ax, int ay): x(ax), y(ax) {}
};</lang>
Point can also be parametrized on the coordinate type: <lang 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 };</lang> Of course, a constructor can be added in this case as well.
C#
<lang csharp>struct Point {
public int x, y; public Point(int x, int y) { this.x = x; this.y = y; }
}</lang>
Clean
Record type
<lang clean>:: Point = { x :: Int, y :: Int }</lang>
Parameterized Algebraic type
<lang clean>:: Point a = Point a a // usage: (Point Int)</lang>
Synonym type
<lang clean>:: Point :== (Int, Int)</lang>
D
A struct, it can be inizialized with a Point(x, y) syntax:
<lang d>struct Point { int x, y; }</lang>
It can also be parametrized on the coordinate type:
<lang d>struct Point(T) { T x, y; }
// A point with integer coordinates auto p1 = Point!(int)(3, 5);
// a point with floating point coordinates auto p1 = Point!(float)(3, 5);</lang>
There are also other ways to initialize them. The D language also supports tuples.
Common Lisp
<lang lisp>(defstruct point x y)</lang>
E
<lang e>def makePoint(x, y) {
def point { to getX() { return x } to getY() { return y } } return point
}</lang>
Factor
<lang factor>TUPLE: point x y ;</lang>
Forth
There is no standard structure syntax in Forth, but it is easy to define words for creating and accessing data structures.
<lang forth>: 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</lang>
Some Forths have mechanisms for declaring complex structures. For example, GNU Forth uses this syntax:
<lang forth>struct
cell% field pt>x cell% field pt>y
end-struct point%</lang>
Fortran
In ISO Fortran 90 or later, use a TYPE declaration, "constructor" syntax, and field delimiter syntax: <lang fortran>program typedemo
type rational ! Type declaration integer :: numerator integer :: denominator end type rational type( rational ), parameter :: zero = rational( 0, 1 ) ! Variables initialized type( rational ), parameter :: one = rational( 1, 1 ) ! by constructor syntax 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
end program typedemo ! as integer array</lang>
F#
See the OCaml section as well. Here we create a list of points and print them out. <lang fsharp>type Point = { x : int; y : int }
let points = [
{x = 1; y = 1}; {x = 5; y = 5} ]
Seq.iter (fun p -> printfn "%d,%d" p.x p.y) points</lang>
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
You can make a tuple literal by using a comma-delimited list surrounded by parentheses, without needing to declare the type first:
<lang haskell>p = (2,3)</lang>
The type of p
is (Int, Int)
, using the same comma-delimited list syntax as the literal.
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.
Icon and Unicon
Icon
<lang icon>record Point(x,y)</lang>
Unicon
This Icon solution works in Unicon.
IDL
<lang idl>point = {x: 6 , y: 0 } point.y = 7 print, point
- => { 6 7}</lang>
J
In a "real" J application, points would be represented by arrays of 2 (or N) numbers. None the less, sometimes objects (in the OO sense) are a better representation than arrays, so J supports them:
<lang j> NB. Create a "Point" class
coclass'Point'
NB. Define its constuctor create =: 3 : 0 'X Y' =: y )
NB. Instantiate an instance (i.e. an object) cocurrent 'base' P =: 10 20 conew 'Point'
NB. Interrogate its members X__P
10
Y__P
20</lang>
Java
We use a class: <lang 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 ); }
}</lang>
JavaScript
<lang javascript>var point = new Object(); point.x = 1; point.y = 2;</lang>
JSON
<lang json>var point = {
x:1, y:2
};</lang>
Logo
In Logo, a point is represented by a list of two numbers. For example, this will draw a triangle: <lang logo>setpos [100 100] setpos [100 0] setpos [0 0] show pos ; [0 0]</lang> 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: <lang logo>until [(first mousepos) < 0] [ifelse button? [pendown] [penup] setpos mousepos]</lang>
MAXScript
Point is a built-in object type in MAX, so... <lang maxscript>struct myPoint (x, y) newPoint = myPoint x:3 y:4</lang> In practice however, you'd use MAX's built in Point2 type <lang maxscript>newPoint = Point2 3 4</lang>
Modula-3
<lang modula3>TYPE Point = RECORD
x, y: INTEGER;
END;</lang>
Usage:
VAR point: Point; ... point := Point{3, 4};
or
point := Point{x := 3, y := 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.
<lang ocaml>type tree = Empty
| Leaf of int | Node of tree * tree
let t1 = Node (Leaf 1, Node (Leaf 2, Leaf 3))</lang>
Record Type
<lang ocaml>type point = { x : int; y : int }</lang>
How to construct a point:
<lang ocaml>let p = { x = 4; y = 5 }</lang>
You can use the dot (".") to access fields. <lang ocaml>p.x (* evaluates to 4 *)</lang>
Fields can be optionally declared to be mutable: <lang ocaml>type mutable_point = { mutable x2 : int; mutable y2 : int }</lang>
Then they can be assigned using the assignment operator "<-" <lang ocaml>let p2 = { x2 = 4; y2 = 5 } in
p2.x2 <- 6; p2 (* evaluates to { x2 = 6; y2 = 5 } *)</lang>
Tuple Type
You can make a tuple literal by using a comma-delimited list, optionally surrounded by parentheses, without needing to declare the type first:
<lang ocaml>let p = (2,3)</lang>
The type of p
is a product (indicated by *
) of the types of the components:
# let p = (2,3);; val p : int * int = (2, 3)
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.
<lang openedge>def temp-table point
field x as int field y as int .</lang>
Another option would be a simple class.
Oz
A point can be represented by using a record value: <lang oz>P = point(x:1 y:2)</lang>
Now we can access the components by name: P.x and P.y Often such values are deconstructed by pattern matching: <lang oz>case P of point(x:X y:Y) then
{Show X} {Show Y}
end</lang>
Pascal
<lang pascal>type point = record
x, y: integer; end;</lang>
Perl
Array
<lang perl>my @point = (3, 8);</lang>
Hash
<lang perl>my %point = (
x => 3, y => 8
);</lang>
Class instance
<lang perl>package Point;
use strict; use base 'Class::Struct'
x => '$', y => '$',
my $point = Point->new(x => 3, y => 8);</lang>
Perl 6
Array
<lang perl6>my @point = 3, 8;</lang>
Hash
<lang perl6>my %point = x => 3, y => 8;</lang>
Class instance
<lang perl6>class Point { has $.x is rw; has $.y is rw; } my Point $point .= new(x => 3, y => 8);</lang>
PHP
<lang 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;</lang>
<lang php># Using array $point = array('x' => 1, 'y' => 2);
list($x, $y) = $point; echo $x, ' ', $y, "\n";
- or simply:
echo $point['x'], ' ', $point['y'], "\n";</lang>
<lang php># Using class class Point {
function __construct($x, $y) { $this->x = $x; $this->y = $y; } function __tostring() { return $this->x . ' ' . $this->y . "\n"; }
} $point = new Point(1, 2); echo $point; # will call __tostring() in later releases of PHP 5.2; before that, it won't work so good.</lang>
PicoLisp
<lang PicoLisp>(class +Point)
(dm T (X Y)
(=: x X) (=: y Y) )
(setq P (new '(+Point) 3 4))
(show P)</lang> Output:
$52717735311266 (+Point) y 4 x 3
PL/I
<lang PL/I> define structure
1 point, 2 x float, 2 y float;
</lang>
Pop11
<lang pop11>uses objectclass; define :class Point;
slot x = 0; slot y = 0;
enddefine;</lang>
PureBasic
Basic structuresare implemented as; <lang PureBasic>Structure MyPoint
X.i Y.i
EndStructure</lang>
If needed StructureUnion can be used to optimize the structures
<lang PureBasic>Structure MyFileDate
name.s StructureUnion Date_as_txt.s Date_in_Ticks.l EndStructureUnion
EndStructure</lang>
Python
The simplest way it to use a tuple, or a list if it should be mutable: <lang python>X, Y = 0, 1 p = (3, 4) p = [3, 4]
print p[X]</lang>
If needed, you can use class:
<lang python>class Point:
def __init__(self, x=0, y=0): self.x = x self.y = y
p = Point() print p.x</lang>
One could also simply instantiate a generic object and "monkeypatch" it:
<lang python>class MyObject(object): pass 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</lang>
Named Tuples
As of Python 2.6 one can use the collections.namedtuple factory to create classes which associate field names with elements of a tuple. This allows one to perform all normal operations on the contained tuples (access by indices or slices, packing and unpacking) while also allowing elements to be accessed by name.
<lang python>>>> from collections import namedtuple >>> help(namedtuple) Help on function namedtuple in module collections:
namedtuple(typename, field_names, verbose=False)
Returns a new subclass of tuple with named fields. >>> Point = namedtuple('Point', 'x y') >>> Point.__doc__ # docstring for the new class 'Point(x, y)' >>> p = Point(11, y=22) # instantiate with positional args or keywords >>> p[0] + p[1] # indexable like a plain tuple 33 >>> x, y = p # unpack like a regular tuple >>> x, y (11, 22) >>> p.x + p.y # fields also accessable by name 33 >>> d = p._asdict() # convert to a dictionary >>> d['x'] 11 >>> Point(**d) # convert from a dictionary Point(x=11, y=22) >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields Point(x=100, y=22)
>>></lang>
R
R uses the list data type for compound data. <lang R>mypoint <- list(x=3.4, y=6.7)
- $x
- [1] 3.4
- $y
- [1] 6.7
mypoint$x # 3.4
list(a=1:10, b="abc", c=runif(10), d=list(e=1L, f=TRUE))
- $a
- [1] 1 2 3 4 5 6 7 8 9 10
- $b
- [1] "abc"
- $c
- [1] 0.64862897 0.73669435 0.11138945 0.10408015 0.46843836 0.32351247
- [7] 0.20528914 0.78512472 0.06139691 0.76937113
- $d
- $d$e
- [1] 1
- $d$f
- [1] TRUE</lang>
Ruby
<lang ruby>Point = Struct.new(:x,:y) p = Point.new(6,7) p.y=3 puts p => #<struct Point x=6, y=3></lang>
Scheme
Using SRFI 9: <lang scheme>(define-record-type point
(make-point x y) point? (x point-x) (y point-y))</lang>
SIMPOL
The point
type is pre-defined in [SIMPOL], so we will call this mypoint.
<lang simpol>type mypoint
embed integer x integer y
end type</lang>
The embed
keyword is used here as a toggle to indicate that all following properties are embedded in the type. The other toggle is reference
, which only places a reference to an object in the type, but the reference assigned before the property can be used. These keywords can also be placed on the same line, but then they only apply to that line of the type definition.
A type in [SIMPOL] can be just a container of values and other structures, but it can also include methods. These are implemented outside the type definition, but must be part of the same compiled unit.
<lang simpol>type mypoint
embed integer x integer y
end type
function mypoint.new(mypoint me, integer x, integer y)
me.x = x me.y = y
end function me</lang>
SNOBOL4
<lang snobol> data('point(x,y)') p1 = point(10,20) p2 = point(10,40) output = "Point 1 (" x(p1) "," y(p1) ")" output = "Point 2 (" x(p2) "," y(p2) ")" end</lang>
Standard ML
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.
<lang sml>datatype tree = Empty
| Leaf of int | Node of tree * tree
val t1 = Node (Leaf 1, Node (Leaf 2, Leaf 3))</lang>
Tuple Type
You can make a tuple literal by using a comma-delimited list surrounded by parentheses, without needing to declare the type first:
<lang sml>val p = (2,3)</lang>
The type of p
is a product (indicated by *
) of the types of the components:
- val p = (2,3); val p = (2,3) : int * int
You can extract elements of the tuple using the #N
syntax:
- #2 p; val it = 3 : int
The #2
above extracts the second field of its argument.
Record Type
Records are like tuples but with field names.
You can make a record literal by using a comma-delimited list of key = value
pairs surrounded by curly braces, without needing to declare the type first:
<lang sml>val p = { x = 4, y = 5 }</lang>
The type of p
is a comma-delimited list of key:type
pairs of the types of the fields:
- val p = { x = 4, y = 5 }; val p = {x=4,y=5} : {x:int, y:int}
You can extract elements of the tuple using the #name
syntax:
- #y p; val it = 5 : int
The #y
above extracts the field named "y" of its argument.
Tcl
This appears to be a sub-functionality of a proper associative array: <lang tcl>array set point {x 4 y 5} set point(y) 7 puts "Point is {$point(x),$point(y)}"
- => Point is {4,7}</lang>
TI-89 BASIC
TI-89 BASIC does not have user-defined data structures. The specific example of a point is best handled by using the built-in vectors or complex numbers.
Ursala
A record type with two untyped fields named x
and y
can be declared like this.
<lang Ursala>point :: x y</lang>
A constant instance of the record can be declared like this.
<lang Ursala>p = point[x: 'foo',y: 'bar']</lang>
A function returning a value of this type can be defined like this,
<lang Ursala>f = point$[x: g,y: h]</lang>
where g
and h
are functions. Then f(p)
would evaluate to
point[x: g(p),y: h(p)]
for a given argument p
. Accessing the fields of
a record can be done like this.
<lang Ursala>t = ~x p
u = ~y p</lang>
where p
is any expression of the defined type. A real application wouldn't be written
this way because pairs of values (x,y)
are a common idiom.
Visual Basic .NET
Simple Structures
This shows a structure in its simpest form.
<lang vbnet>Structure Simple_Point
Public X, Y As Integer
End Structure</lang>
Immutable Structures
In Visual Basic, mutable strucutures are difficult to use properly and should only be used when performance measurements warrant it. The rest of the time, immutable structures should be used. Below is the same structure seen before, but in an immutable form.
<lang vbnet>Structure Immutable_Point
Private m_X As Integer Private m_Y As Integer
Public Sub New(ByVal x As Integer, ByVal y As Integer) m_X = x m_Y = y End Sub
Public ReadOnly Property X() As Integer Get Return m_X End Get End Property
Public ReadOnly Property Y() As Integer Get Return m_Y End Get End Property
End Structure</lang>
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. <lang xml><point x="20" y="30"/>
<fo:block>Point = <xsl:value-of select="@x"/>, <xsl:value-of select="@y"/></fo:block></lang>
Children
More complex, multivariate, and nested data structures can be represented using child nodes. <lang xml><circle>
<point> <x>20</x> <y>30</y> </point> <radius>10</radius>
</circle>
</lang>
<fo:block>Circle center = <xsl:value-of select="point/x"/>, <xsl:value-of select="point/y"/></fo:block>
- Programming Tasks
- Basic language learning
- Data Structures
- ActionScript
- Ada
- ALGOL 68
- AmigaE
- AWK
- BASIC
- C
- C++
- C sharp
- Clean
- D
- Common Lisp
- E
- Factor
- Forth
- Fortran
- F Sharp
- Haskell
- Icon
- Unicon
- IDL
- J
- Java
- JavaScript
- JSON
- Logo
- MAXScript
- Modula-3
- OCaml
- OpenEdge/Progress
- Oz
- Pascal
- Perl
- Perl 6
- PHP
- PicoLisp
- PL/I
- Pop11
- PureBasic
- Python
- R
- Ruby
- Scheme
- SIMPOL
- SNOBOL4
- Standard ML
- Tcl
- TI-89 BASIC
- Ursala
- Visual Basic .NET
- XSLT