Compound data type: Difference between revisions
(→{{header|Python}}: === Dictionary ===) |
(PascalABC.NET) |
||
(122 intermediate revisions by 74 users not shown) | |||
Line 1: | Line 1: | ||
{{task| |
{{task|rBasic language learning}} |
||
{{Data structure}} |
|||
Create a compound data type Point(x,y). |
|||
;Task: |
|||
Create a compound data type: |
|||
<big> Point(x,y) </big> |
|||
A compound data type is one that holds multiple independent values. |
|||
;Related task: |
|||
* [[Enumeration]] |
|||
A compound data type is one that holds multiple independent values. See also [[Enumeration]]. |
|||
{{Template:See also lists}} |
{{Template:See also lists}} |
||
<br><br> |
|||
=={{header|11l}}== |
|||
<syntaxhighlight lang="11l">T Point |
|||
Int x, y |
|||
F (x, y) |
|||
.x = x |
|||
.y = y</syntaxhighlight> |
|||
=={{header|ACL2}}== |
=={{header|ACL2}}== |
||
< |
<syntaxhighlight lang="lisp">(defstructure point |
||
(x (:assert (rationalp x))) |
(x (:assert (rationalp x))) |
||
(y (:assert (rationalp y)))) |
(y (:assert (rationalp y)))) |
||
Line 14: | Line 34: | ||
(assign p1 (update-point (@ p1) :x 3)) ; Update the x value |
(assign p1 (update-point (@ p1) :x 3)) ; Update the x value |
||
(point-x (@ p1)) |
(point-x (@ p1)) |
||
(point-p (@ p1)) ; Recognizer for points</ |
(point-p (@ p1)) ; Recognizer for points</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre>((:X . 1) (:Y . 2)) |
<pre>((:X . 1) (:Y . 2)) |
||
1 |
1 |
||
Line 22: | Line 42: | ||
3 |
3 |
||
T</pre> |
T</pre> |
||
=={{header|6502 Assembly}}== |
|||
The method below is a bit unusual compared to [[C]], where each member of a struct is stored consecutively. The addressing modes of 6502 make it much more efficient to store each member of many different structs consecutively. In other words, the index used to offset into <code>point_x</code> represents which instance of the data type the CPU is accessing. Of course, this assumes that you're willing to declare in advance how many active instances of that data type you'll ever have at once, a very frequent practice in the 8-bit assembly world but is absolutely ludicrous in high-level languages. |
|||
NESASM3 syntax: |
|||
<syntaxhighlight lang="6502asm">MAX_POINT_OBJECTS = 64 ; define a constant |
|||
.rsset $0400 ; reserve memory storage starting at address $0400 |
|||
point_x .rs MAX_POINT_OBJECTS ; reserve 64 bytes for x-coordinates |
|||
point_y .rs MAX_POINT_OBJECTS ; reserve 64 bytes for y-coordinates</syntaxhighlight> |
|||
VASM syntax: |
|||
<syntaxhighlight lang="6502asm">MAX_POINT_OBJECTS equ 64 |
|||
point_ram equ $0400 |
|||
point_x equ point_ram |
|||
point_y equ point_ram+MAX_POINT_OBJECTS</syntaxhighlight> |
|||
So, for example, let's say we want to load our third (zero-indexed) point variable and copy it to zero page RAM addresses $00 and $01. We would do the following: |
|||
<syntaxhighlight lang="6502asm">MAX_POINT_OBJECTS equ 64 |
|||
point_ram equ $0400 |
|||
point_x equ point_ram |
|||
point_y equ point_ram+MAX_POINT_OBJECTS |
|||
LDX #3 |
|||
LDA point_x,x |
|||
STA $00 |
|||
LDA point_y,x |
|||
STA $01</syntaxhighlight> |
|||
=={{header|Action!}}== |
|||
{{libheader|Action! Tool Kit}} |
|||
<syntaxhighlight lang="action!">INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit |
|||
DEFINE REALPTR="CARD" |
|||
TYPE PointI=[INT x,y] |
|||
TYPE PointR=[REALPTR rx,ry] |
|||
PROC Main() |
|||
PointI p1 |
|||
PointR p2 |
|||
REAL realx,realy |
|||
Put(125) PutE() ;clear screen |
|||
p1.x=123 |
|||
p1.y=4567 |
|||
ValR("12.34",realx) |
|||
ValR("5.6789",realy) |
|||
p2.rx=realx |
|||
p2.ry=realy |
|||
PrintF("Integer point p1=(%I,%I)%E",p1.x,p1.y) |
|||
Print("Real point p2=(") |
|||
PrintR(p2.rx) Print(",") |
|||
PrintR(p2.ry) Print(")") |
|||
RETURN</syntaxhighlight> |
|||
{{out}} |
|||
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Compound_data_type.png Screenshot from Atari 8-bit computer] |
|||
<pre> |
|||
Integer point p1=(123,4567) |
|||
Real point p2=(12.34,5.6789) |
|||
</pre> |
|||
=={{header|ActionScript}}== |
=={{header|ActionScript}}== |
||
< |
<syntaxhighlight lang="actionscript">package |
||
{ |
{ |
||
public class Point |
public class Point |
||
Line 37: | Line 123: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
===Tagged Type=== |
===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 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. |
||
< |
<syntaxhighlight lang="ada">type Point is tagged record |
||
X : Integer := 0; |
X : Integer := 0; |
||
Y : Integer := 0; |
Y : Integer := 0; |
||
end record;</ |
end record;</syntaxhighlight> |
||
===Record Type=== |
===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 record types are not extensible through inheritance. Without the reserved word ''tagged'' the record does not belong to an inheritance hierarchy. |
||
< |
<syntaxhighlight lang="ada">type Point is record |
||
X : Integer := 0; |
X : Integer := 0; |
||
Y : Integer := 0; |
Y : Integer := 0; |
||
end record;</ |
end record;</syntaxhighlight> |
||
====Parameterized Types==== |
====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. |
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. |
||
< |
<syntaxhighlight lang="ada">type Person (Gender : Gender_Type) is record |
||
Name : Name_String; |
Name : Name_String; |
||
Age : Natural; |
Age : Natural; |
||
Line 66: | Line 152: | ||
null; |
null; |
||
end case; |
end case; |
||
end record;</ |
end record;</syntaxhighlight> |
||
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. |
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. |
||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
===Tagged Type=== |
===Tagged Type=== |
||
ALGOL 68 has only tagged-union/discriminants. And the tagging was strictly done by the ''type'' (MODE) of the members. |
ALGOL 68 has only tagged-union/discriminants. And the tagging was strictly done by the ''type'' (MODE) of the members. |
||
< |
<syntaxhighlight lang="algol68">MODE UNIONX = UNION( |
||
STRUCT(REAL r, INT i), |
STRUCT(REAL r, INT i), |
||
INT, |
INT, |
||
Line 78: | Line 165: | ||
STRUCT(REAL rr), |
STRUCT(REAL rr), |
||
STRUCT([]REAL r) |
STRUCT([]REAL r) |
||
);</ |
);</syntaxhighlight> |
||
To extract the apropriate member of a UNION a '''conformity-clause''' has to be used. |
To extract the apropriate member of a UNION a '''conformity-clause''' has to be used. |
||
< |
<syntaxhighlight lang="algol68">UNIONX data := 6.6; |
||
CASE data IN |
CASE data IN |
||
(INT i): printf(($"r: "gl$,i)), |
(INT i): printf(($"r: "gl$,i)), |
||
Line 88: | Line 175: | ||
OUT |
OUT |
||
printf($"Other cases"l$) |
printf($"Other cases"l$) |
||
ESAC;</ |
ESAC;</syntaxhighlight> |
||
The '''conformity-clause''' does mean that ALGOL 68 avoids the need for |
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, |
[[duck typing]], but it also makes the tagged-union kinda tough to use, |
||
Line 95: | Line 182: | ||
ALGOL 68 record types are not extensible through inheritance but they |
ALGOL 68 record types are not extensible through inheritance but they |
||
may be part of a larger STRUCT composition. |
may be part of a larger STRUCT composition. |
||
< |
<syntaxhighlight lang="algol68">MODE POINT = STRUCT( |
||
INT x, |
INT x, |
||
INT y |
INT y |
||
);</ |
);</syntaxhighlight> |
||
====Parameterized Types==== |
====Parameterized Types==== |
||
An ALGOL 68 record type can contain a tagged-union/discriminant. The |
An ALGOL 68 record type can contain a tagged-union/discriminant. The |
||
tagged-union/discriminant is used to choose between internal structural |
tagged-union/discriminant is used to choose between internal structural |
||
representations. |
representations. |
||
< |
<syntaxhighlight lang="algol68">MODE PERSON = STRUCT( |
||
STRING name, |
STRING name, |
||
REAL age, |
REAL age, |
||
Line 111: | Line 198: | ||
VOID |
VOID |
||
) gender details |
) gender details |
||
);</ |
);</syntaxhighlight> |
||
In this case every PERSON will have the attributes of gender details, name, age, |
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. |
and weight. A PERSON may or may not have a beard. The sex is implied by the tagging. |
||
=={{header|ALGOL W}}== |
|||
<syntaxhighlight lang="algolw">begin |
|||
% create the compound data type % |
|||
record Point( real x, y ); |
|||
% declare a Point variable % |
|||
reference(Point) p; |
|||
% assign a value to p % |
|||
p := Point( 1, 0.5 ); |
|||
% access the fields of p - note Algol W uses x(p) where many languages would use p.x % |
|||
write( x(p), y(p) ) |
|||
end.</syntaxhighlight> |
|||
=={{header|AmigaE}}== |
=={{header|AmigaE}}== |
||
< |
<syntaxhighlight lang="amigae">OBJECT point |
||
x, y |
x, y |
||
ENDOBJECT |
ENDOBJECT |
||
Line 124: | Line 223: | ||
NEW pt |
NEW pt |
||
-> Floats are also stored as integer types making |
|||
pt.x := 10.4 |
|||
-> the float conversion operator necessary. |
|||
pt.y := 3.14 |
|||
pt.x := !10.4 |
|||
pt.y := !3.14 |
|||
END pt |
END pt |
||
ENDPROC</ |
ENDPROC</syntaxhighlight> |
||
=={{header|ARM Assembly}}== |
|||
{{works with|as|Raspberry Pi}} |
|||
<syntaxhighlight lang="arm assembly"> |
|||
/* ARM assembly Raspberry PI */ |
|||
/* program structure.s */ |
|||
/************************************/ |
|||
/* Constantes */ |
|||
/************************************/ |
|||
.equ STDOUT, 1 @ Linux output console |
|||
.equ EXIT, 1 @ Linux syscall |
|||
.equ WRITE, 4 @ Linux syscall |
|||
/*******************************************/ |
|||
/* Structures */ |
|||
/********************************************/ |
|||
.struct 0 |
|||
point_x: @ x coordinate |
|||
.struct point_x + 4 |
|||
point_y: @ y coordinate |
|||
.struct point_y + 4 |
|||
point_end: @ end structure point |
|||
/*********************************/ |
|||
/* Initialized data */ |
|||
/*********************************/ |
|||
.data |
|||
sMessResult: .ascii "value x : " |
|||
sMessValeur: .fill 11, 1, ' ' @ size => 11 |
|||
szCarriageReturn: .asciz "\n" |
|||
/*********************************/ |
|||
/* UnInitialized data */ |
|||
/*********************************/ |
|||
.bss |
|||
stPoint: .skip point_end @ reservation place in memory |
|||
/*********************************/ |
|||
/* code section */ |
|||
/*********************************/ |
|||
.text |
|||
.global main |
|||
main: @ entry of program |
|||
ldr r1,iAdrstPoint |
|||
mov r0,#5 @ x value |
|||
str r0,[r1,#point_x] |
|||
mov r0,#10 @ y value |
|||
str r0,[r1,#point_y] |
|||
@ display value |
|||
ldr r2,iAdrstPoint |
|||
ldr r0,[r2,#point_x] |
|||
ldr r1,iAdrsMessValeur |
|||
bl conversion10 @ call conversion decimal |
|||
ldr r0,iAdrsMessResult |
|||
bl affichageMess @ display message |
|||
100: @ standard end of the program |
|||
mov r0, #0 @ return code |
|||
mov r7, #EXIT @ request to exit program |
|||
svc #0 @ perform the system call |
|||
iAdrsMessValeur: .int sMessValeur |
|||
iAdrszCarriageReturn: .int szCarriageReturn |
|||
iAdrsMessResult: .int sMessResult |
|||
iAdrstPoint: .int stPoint |
|||
/******************************************************************/ |
|||
/* display text with size calculation */ |
|||
/******************************************************************/ |
|||
/* r0 contains the address of the message */ |
|||
affichageMess: |
|||
push {r0,r1,r2,r7,lr} @ save registres |
|||
mov r2,#0 @ counter length |
|||
1: @ loop length calculation |
|||
ldrb r1,[r0,r2] @ read octet start position + index |
|||
cmp r1,#0 @ if 0 its over |
|||
addne r2,r2,#1 @ else add 1 in the length |
|||
bne 1b @ and loop |
|||
@ so here r2 contains the length of the message |
|||
mov r1,r0 @ address message in r1 |
|||
mov r0,#STDOUT @ code to write to the standard output Linux |
|||
mov r7, #WRITE @ code call system "write" |
|||
svc #0 @ call systeme |
|||
pop {r0,r1,r2,r7,lr} @ restaur des 2 registres */ |
|||
bx lr @ return |
|||
/******************************************************************/ |
|||
/* Converting a register to a decimal unsigned */ |
|||
/******************************************************************/ |
|||
/* r0 contains value and r1 address area */ |
|||
/* r0 return size of result (no zero final in area) */ |
|||
/* area size => 11 bytes */ |
|||
.equ LGZONECAL, 10 |
|||
conversion10: |
|||
push {r1-r4,lr} @ save registers |
|||
mov r3,r1 |
|||
mov r2,#LGZONECAL |
|||
1: @ start loop |
|||
bl divisionpar10U @ unsigned r0 <- dividende. quotient ->r0 reste -> r1 |
|||
add r1,#48 @ digit |
|||
strb r1,[r3,r2] @ store digit on area |
|||
cmp r0,#0 @ stop if quotient = 0 |
|||
subne r2,#1 @ else previous position |
|||
bne 1b @ and loop |
|||
@ and move digit from left of area |
|||
mov r4,#0 |
|||
2: |
|||
ldrb r1,[r3,r2] |
|||
strb r1,[r3,r4] |
|||
add r2,#1 |
|||
add r4,#1 |
|||
cmp r2,#LGZONECAL |
|||
ble 2b |
|||
@ and move spaces in end on area |
|||
mov r0,r4 @ result length |
|||
mov r1,#' ' @ space |
|||
3: |
|||
strb r1,[r3,r4] @ store space in area |
|||
add r4,#1 @ next position |
|||
cmp r4,#LGZONECAL |
|||
ble 3b @ loop if r4 <= area size |
|||
100: |
|||
pop {r1-r4,lr} @ restaur registres |
|||
bx lr @return |
|||
/***************************************************/ |
|||
/* division par 10 unsigned */ |
|||
/***************************************************/ |
|||
/* r0 dividende */ |
|||
/* r0 quotient */ |
|||
/* r1 remainder */ |
|||
divisionpar10U: |
|||
push {r2,r3,r4, lr} |
|||
mov r4,r0 @ save value |
|||
ldr r3,iMagicNumber @ r3 <- magic_number raspberry 1 2 |
|||
umull r1, r2, r3, r0 @ r1<- Lower32Bits(r1*r0) r2<- Upper32Bits(r1*r0) |
|||
mov r0, r2, LSR #3 @ r2 <- r2 >> shift 3 |
|||
add r2,r0,r0, lsl #2 @ r2 <- r0 * 5 |
|||
sub r1,r4,r2, lsl #1 @ r1 <- r4 - (r2 * 2) = r4 - (r0 * 10) |
|||
pop {r2,r3,r4,lr} |
|||
bx lr @ leave function |
|||
iMagicNumber: .int 0xCCCCCCCD |
|||
</syntaxhighlight> |
|||
=={{header|Arturo}}== |
|||
<syntaxhighlight lang="arturo">point: #[ |
|||
x: 10 |
|||
y: 20 |
|||
] |
|||
print point</syntaxhighlight> |
|||
{{out}} |
|||
<pre>[x:10 y:20]</pre> |
|||
=={{header|ATS}}== |
|||
There are numerous ways to do this. The simplest is to use an "unboxed" tuple type: |
|||
<syntaxhighlight lang="ats">typedef point (t : t@ype+) = @(t, t) |
|||
val p : point double = (1.0, 3.0)</syntaxhighlight> |
|||
If one insists both that the type be unique (as opposed to an alias for a tuple) and that the notation to create a point be '''Point (x, y)''', then the following works: |
|||
<syntaxhighlight lang="ats">datatype point (t : t@ype+) = |
|||
| Point of (t, t) |
|||
val p : point double = Point (1.0, 3.0)</syntaxhighlight> |
|||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
{{works with | AutoHotkey_L}} |
{{works with | AutoHotkey_L}} |
||
[[wp:Monkey_patch|monkeypatched]] example. |
[[wp:Monkey_patch|monkeypatched]] example. |
||
< |
<syntaxhighlight lang="autohotkey">point := Object() |
||
point.x := 1 |
point.x := 1 |
||
point.y := 0 |
point.y := 0 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
As usual, arrays are the only data type more complex than a number or a string. |
As usual, arrays are the only data type more complex than a number or a string.<br> |
||
Use quotes around constant strings as element selectors: |
|||
<lang awk>p["x"]=10 |
|||
<syntaxhighlight lang="awk">BEGIN { |
|||
p["y"]=42</lang> |
|||
p["x"]=10 |
|||
p["y"]=42 |
|||
z = "ZZ" |
|||
p[ z ]=999 |
|||
p[ 4 ]=5 |
|||
for (i in p) print( i, ":", p[i] ) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
4 : 5 |
|||
x : 10 |
|||
y : 42 |
|||
ZZ : 999</pre> |
|||
=={{header|Axe}}== |
|||
Axe does not have language support for custom data structures. However, they can be implemented from scratch using memory directly. |
|||
<syntaxhighlight lang="axe">Lbl POINT |
|||
r₂→{r₁}ʳ |
|||
r₃→{r₁+2}ʳ |
|||
r₁ |
|||
Return</syntaxhighlight> |
|||
To initialize a POINT at memory address L₁ with (x, y) = (5, 10): |
|||
<syntaxhighlight lang="axe">POINT(L₁,5,10)</syntaxhighlight> |
|||
The caller must ensure the buffer has enough free space to contain the object (in this case, 4 bytes). |
|||
=={{header|BASIC}}== |
=={{header|BASIC}}== |
||
Line 146: | Line 449: | ||
{{works with|PowerBASIC}} |
{{works with|PowerBASIC}} |
||
< |
<syntaxhighlight lang="qb">TYPE Point |
||
x AS INTEGER |
x AS INTEGER |
||
y AS INTEGER |
y AS INTEGER |
||
END TYPE</ |
END TYPE</syntaxhighlight> |
||
=={{header|BBC BASIC}}== |
=={{header|BBC BASIC}}== |
||
{{works with|BBC BASIC for Windows}} |
{{works with|BBC BASIC for Windows}} |
||
< |
<syntaxhighlight lang="bbcbasic"> DIM Point{x%, y%}</syntaxhighlight> |
||
=={{header|Bracmat}}== |
=={{header|Bracmat}}== |
||
Line 160: | Line 463: | ||
So we go object oriented and create a 'type' Point. We show that <code>x</code> and <code>y</code> are independent by changing the value of <code>x</code> and checking that <code>y</code> didn't change. |
So we go object oriented and create a 'type' Point. We show that <code>x</code> and <code>y</code> are independent by changing the value of <code>x</code> and checking that <code>y</code> didn't change. |
||
Bracmat does not have other typing systems than duck typing. The variable <code>Point</code> is not a class, but an object in its own right. The <code>new$</code> function creates a copy of <code>Point</code>. |
Bracmat does not have other typing systems than duck typing. The variable <code>Point</code> is not a class, but an object in its own right. The <code>new$</code> function creates a copy of <code>Point</code>. |
||
< |
<syntaxhighlight lang="bracmat">( ( Point |
||
= (x=) |
= (x=) |
||
(y=) |
(y=) |
||
Line 170: | Line 473: | ||
& 7:?(pt..x) |
& 7:?(pt..x) |
||
& out$(!(pt..x) !(pt..y)) |
& out$(!(pt..x) !(pt..y)) |
||
);</ |
);</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre>3 4 |
<pre>3 4 |
||
7 4</pre> |
7 4</pre> |
||
Line 183: | Line 486: | ||
=={{header|C}}== |
=={{header|C}}== |
||
< |
<syntaxhighlight lang="c">typedef struct Point |
||
{ |
{ |
||
int x; |
int x; |
||
int y; |
int y; |
||
} Point;</ |
} Point;</syntaxhighlight> |
||
=={{header|C sharp|C#}}== |
|||
<syntaxhighlight lang="csharp">struct Point |
|||
{ |
|||
public int x, y; |
|||
public Point(int x, int y) { |
|||
this.x = x; |
|||
this.y = y; |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|C++}}== |
=={{header|C++}}== |
||
< |
<syntaxhighlight lang="cpp">struct Point |
||
{ |
{ |
||
int x; |
int x; |
||
int y; |
int y; |
||
};</ |
};</syntaxhighlight> |
||
It is also possible to add a constructor (this allows the use of <tt>Point(x, y)</tt> in expressions): |
It is also possible to add a constructor (this allows the use of <tt>Point(x, y)</tt> in expressions): |
||
< |
<syntaxhighlight lang="cpp">struct Point |
||
{ |
{ |
||
int x; |
int x; |
||
int y; |
int y; |
||
Point(int ax, int ay): x(ax), y(ax) {} |
Point(int ax, int ay): x(ax), y(ax) {} |
||
};</ |
};</syntaxhighlight> |
||
Point can also be parametrized on the coordinate type: |
Point can also be parametrized on the coordinate type: |
||
< |
<syntaxhighlight lang="cpp">template<typename Coordinate> struct point |
||
{ |
{ |
||
Coordinate x, y; |
Coordinate x, y; |
||
Line 214: | Line 528: | ||
// a point with floating point coordinates |
// a point with floating point coordinates |
||
Point<float> point2 = { 1.7, 3.6 };</ |
Point<float> point2 = { 1.7, 3.6 };</syntaxhighlight> |
||
Of course, a constructor can be added in this case as well. |
Of course, a constructor can be added in this case as well. |
||
=={{header|C sharp|C#}}== |
|||
<lang csharp>struct Point |
|||
{ |
|||
public int x, y; |
|||
public Point(int x, int y) { |
|||
this.x = x; |
|||
this.y = y; |
|||
} |
|||
}</lang> |
|||
=={{header|Clean}}== |
=={{header|Clean}}== |
||
===Record type=== |
===Record type=== |
||
< |
<syntaxhighlight lang="clean">:: Point = { x :: Int, y :: Int }</syntaxhighlight> |
||
===Parameterized Algebraic type=== |
===Parameterized Algebraic type=== |
||
< |
<syntaxhighlight lang="clean">:: Point a = Point a a // usage: (Point Int)</syntaxhighlight> |
||
===Synonym type=== |
===Synonym type=== |
||
< |
<syntaxhighlight lang="clean">:: Point :== (Int, Int)</syntaxhighlight> |
||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
< |
<syntaxhighlight lang="clojure">(defrecord Point [x y])</syntaxhighlight> |
||
This defines a datatype with constructor ''Point.'' and accessors '':x'' and '':y'' : |
This defines a datatype with constructor ''Point.'' and accessors '':x'' and '':y'' : |
||
< |
<syntaxhighlight lang="clojure">(def p (Point. 0 1)) |
||
(assert (= 0 (:x p))) |
(assert (= 0 (:x p))) |
||
(assert (= 1 (:y p)))</ |
(assert (= 1 (:y p)))</syntaxhighlight> |
||
=={{header|CLU}}== |
|||
CLU has two types of compound datatypes: ''struct''s, which are immutable, and ''record''s, which are mutable. |
|||
Aside from this, they work the same way. |
|||
<syntaxhighlight lang="clu">% Definitions |
|||
point = struct[x, y: int] |
|||
mutable_point = record[x, y: int] |
|||
% Initialization |
|||
p: point := point${x: 10, y: 20} |
|||
mp: mutable_point := mutable_point${x: 10, y: 20}</syntaxhighlight> |
|||
The fields can be accessed using the <code>.</code> syntax: |
|||
<syntaxhighlight lang="clu">foo := p.x |
|||
bar := p.y</syntaxhighlight> |
|||
''Record''s, but not ''struct''s, allow updating the fields in the same way. |
|||
<syntaxhighlight lang="clu">mp.x := 30 |
|||
mp.y := 40</syntaxhighlight> |
|||
It should be noted that the special forms <code>p.x</code> and <code>mp.x := value</code> |
|||
are really only syntactic sugar, they are equivalent to the following method calls: |
|||
<syntaxhighlight lang="clu">foo := point$get_x(p) |
|||
bar := point$get_y(p)</syntaxhighlight> |
|||
<syntaxhighlight lang="clu">mutable_point$set_x(mp, 30) |
|||
mutable_point$set_y(mp, 40)</syntaxhighlight> |
|||
=={{header|COBOL}}== |
|||
A compound data item description is possible in COBOL as a subdivided record: |
|||
<syntaxhighlight lang="cobol"> DATA DIVISION. |
|||
WORKING-STORAGE SECTION. |
|||
01 Point. |
|||
05 x USAGE IS BINARY-SHORT. |
|||
05 y USAGE IS BINARY-SHORT.</syntaxhighlight> |
|||
Here the record <code>Point</code> has the subdivisions <code>x</code> and <code>y</code>, both of which are signed 16-bit binary integers. |
|||
=={{header|CoffeeScript}}== |
=={{header|CoffeeScript}}== |
||
< |
<syntaxhighlight lang="coffeescript"> |
||
# Lightweight JS objects (with CS sugar). |
# Lightweight JS objects (with CS sugar). |
||
point = |
point = |
||
Line 265: | Line 605: | ||
console.log p1.distance_from # [Function] |
console.log p1.distance_from # [Function] |
||
console.log p1.distance_from p2 # 13 |
console.log p1.distance_from p2 # 13 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
< |
<syntaxhighlight lang="lisp">CL-USER> (defstruct point (x 0) (y 0)) ;If not provided, x or y default to 0 |
||
POINT</ |
POINT</syntaxhighlight> |
||
In addition to defining the ''point'' data type, the defstruct macro also created constructor and accessor functions: |
In addition to defining the ''point'' data type, the defstruct macro also created constructor and accessor functions: |
||
< |
<syntaxhighlight lang="lisp">CL-USER> (setf a (make-point)) ;The default constructor using the default values for x and y |
||
#S(POINT :X 0 :Y 0) |
#S(POINT :X 0 :Y 0) |
||
CL-USER> (setf b (make-point :x 5.5 :y #C(0 1))) ;Dynamic datatypes are the default |
CL-USER> (setf b (make-point :x 5.5 :y #C(0 1))) ;Dynamic datatypes are the default |
||
Line 284: | Line 623: | ||
3 |
3 |
||
CL-USER> (point-y b) |
CL-USER> (point-y b) |
||
3</ |
3</syntaxhighlight> |
||
=={{header|Crystal}}== |
|||
Crystal's structs work very similarly to objects, but are allocated on the stack instead of the heap, and passed by value instead of by reference. More potential caveats are noted in the [https://crystal-lang.org/reference/syntax_and_semantics/structs.html language reference]. |
|||
<syntaxhighlight lang="ruby">struct Point(T) |
|||
getter x : T |
|||
getter y : T |
|||
def initialize(@x, @y) |
|||
end |
|||
end |
|||
puts Point(Int32).new 13, 12 #=> Point(Int32)(@x=13, @y=12)</syntaxhighlight> |
|||
=={{header|D}}== |
=={{header|D}}== |
||
< |
<syntaxhighlight lang="d">void main() { |
||
// A normal POD struct |
// A normal POD struct |
||
// (if it's nested and it's not static then it has a hidden |
// (if it's nested and it's not static then it has a hidden |
||
Line 333: | Line 684: | ||
static assert(is(p6[0] == int)); |
static assert(is(p6[0] == int)); |
||
static assert(p6[1] == 5); |
static assert(p6[1] == 5); |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Delphi}}== |
=={{header|Delphi}}== |
||
As defined in Types.pas: |
As defined in Types.pas: |
||
< |
<syntaxhighlight lang="delphi"> TPoint = record |
||
X: Longint; |
X: Longint; |
||
Y: Longint; |
Y: Longint; |
||
end; |
end; |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Diego}}== |
|||
<syntaxhighlight lang="diego">use_namespace(rosettacode)_me(); |
|||
add_struct(point)_arg(x,y); |
|||
with_point(point1)_arg(4,3); |
|||
// Since no datatype is specified for the args any datatype can be passed |
|||
with_point(point2)_arg(0.033,👣); |
|||
reset_namespace[];</syntaxhighlight> |
|||
=={{header|E}}== |
=={{header|E}}== |
||
< |
<syntaxhighlight lang="e">def makePoint(x, y) { |
||
def point { |
def point { |
||
to getX() { return x } |
to getX() { return x } |
||
Line 352: | Line 715: | ||
} |
} |
||
return point |
return point |
||
}</ |
}</syntaxhighlight> |
||
=={{header|EchoLisp}}== |
|||
<syntaxhighlight lang="scheme"> |
|||
(lib 'struct) |
|||
(struct Point (x y)) |
|||
(Point 3 4) |
|||
→ #<Point> (3 4) |
|||
;; run-time type checking is possible |
|||
(lib 'types) |
|||
(struct Point (x y)) |
|||
(struct-type Point Number Number) |
|||
(Point 3 4) |
|||
(Point 3 'albert) |
|||
❌ error: #number? : type-check failure : albert → 'Point:y' |
|||
</syntaxhighlight> |
|||
=={{header|Ela}}== |
=={{header|Ela}}== |
||
Line 358: | Line 737: | ||
Ela supports algebraic types: |
Ela supports algebraic types: |
||
< |
<syntaxhighlight lang="ela">type Maybe = None | Some a</syntaxhighlight> |
||
Except of regular algebraic types, Ela also provides a support for open algebraic types - which can be extended any time with new constructors: |
Except of regular algebraic types, Ela also provides a support for open algebraic types - which can be extended any time with new constructors: |
||
< |
<syntaxhighlight lang="ela">opentype Several = One | Two | Three |
||
//Add new constructor to an existing type |
//Add new constructor to an existing type |
||
data Several = Four</ |
data Several = Four</syntaxhighlight> |
||
=={{header|Elena}}== |
|||
ELENA 6.x: |
|||
<syntaxhighlight lang="elena">struct Point |
|||
{ |
|||
int X : prop; |
|||
int Y : prop; |
|||
constructor new(int x, int y) |
|||
{ |
|||
X := x; |
|||
Y := y |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Elixir}}== |
|||
<syntaxhighlight lang="elixir">iex(1)> defmodule Point do |
|||
...(1)> defstruct x: 0, y: 0 |
|||
...(1)> end |
|||
{:module, Point, <<70, 79, 82, ...>>, %Point{x: 0, y: 0}} |
|||
iex(2)> origin = %Point{} |
|||
%Point{x: 0, y: 0} |
|||
iex(3)> pa = %Point{x: 10, y: 20} |
|||
%Point{x: 10, y: 20} |
|||
iex(4)> pa.x |
|||
10 |
|||
iex(5)> %Point{pa | y: 30} |
|||
%Point{x: 10, y: 30} |
|||
iex(6)> %Point{x: px, y: py} = pa # pattern matching |
|||
%Point{x: 10, y: 20} |
|||
iex(7)> px |
|||
10 |
|||
iex(8)> py |
|||
20</syntaxhighlight> |
|||
=={{header|Elm}}== |
|||
<syntaxhighlight lang="elm"> |
|||
--Compound Data type can hold multiple independent values |
|||
--In Elm data can be compounded using List, Tuple, Record |
|||
--In a List |
|||
point = [2,5] |
|||
--This creates a list having x and y which are independent and can be accessed by List functions |
|||
--Note that x and y must be of same data type |
|||
--Tuple is another useful data type that stores different independent values |
|||
point = (3,4) |
|||
--Here we can have multiple data types |
|||
point1 = ("x","y") |
|||
point2 = (3,4.5) |
|||
--The order of addressing matters |
|||
--Using a Record is the best option |
|||
point = {x=3,y=4} |
|||
--To access |
|||
point.x |
|||
point.y |
|||
--Or Use it as a function |
|||
.x point |
|||
.y point |
|||
--Also to alter the value |
|||
{point | x=7} |
|||
{point | y=2} |
|||
{point | x=3,y=4} |
|||
--Each time a new record is generated |
|||
--END |
|||
</syntaxhighlight> |
|||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
< |
<syntaxhighlight lang="erlang"> |
||
-module(records_test). |
-module(records_test). |
||
-compile(export_all). |
-compile(export_all). |
||
Line 379: | Line 824: | ||
P2 = P1#point{x=3.0}, % creates a new point record with x set to 3.0, y is copied from P1 |
P2 = P1#point{x=3.0}, % creates a new point record with x set to 3.0, y is copied from P1 |
||
io:fwrite("X: ~f, Y: ~f~n",[P2#point.x,P2#point.y]). |
io:fwrite("X: ~f, Y: ~f~n",[P2#point.x,P2#point.y]). |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Euphoria}}== |
|||
{{works with|OpenEuphoria}} |
|||
<syntaxhighlight lang="euphoria"> |
|||
enum x, y |
|||
sequence point = {0,0} |
|||
printf(1,"x = %d, y = %3.3f\n",point) |
|||
point[x] = 'A' |
|||
point[y] = 53.42 |
|||
printf(1,"x = %d, y = %3.3f\n",point) |
|||
printf(1,"x = %s, y = %3.3f\n",point) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
x = 0, y = 0.000 |
|||
x = 65, y = 53.420 |
|||
x = A, y = 53.420 |
|||
</pre> |
|||
=={{header|F_Sharp|F#}}== |
|||
See the OCaml section as well. Here we create a list of points and print them out. |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
<lang |
<syntaxhighlight lang="factor">TUPLE: point x y ;</syntaxhighlight> |
||
=={{header|Fantom}}== |
=={{header|Fantom}}== |
||
< |
<syntaxhighlight lang="fantom"> |
||
// define a class to contain the two fields |
// define a class to contain the two fields |
||
// accessors to get/set the field values are automatically generated |
// accessors to get/set the field values are automatically generated |
||
Line 407: | Line 884: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
|||
{{out}} |
|||
<pre> |
<pre> |
||
Point 1 = (0, 0) |
Point 1 = (0, 0) |
||
Line 419: | Line 895: | ||
There is no standard structure syntax in Forth, but it is easy to define words for creating and accessing data structures. |
There is no standard structure syntax in Forth, but it is easy to define words for creating and accessing data structures. |
||
< |
<syntaxhighlight lang="forth">: pt>x ( point -- x ) ; |
||
: pt>y ( point -- y ) CELL+ ; |
: pt>y ( point -- y ) CELL+ ; |
||
: .pt ( point -- ) dup pt>x @ . pt>y @ . ; \ or for this simple structure, 2@ . . |
: .pt ( point -- ) dup pt>x @ . pt>y @ . ; \ or for this simple structure, 2@ . . |
||
Line 425: | Line 901: | ||
create point 6 , 0 , |
create point 6 , 0 , |
||
7 point pt>y ! |
7 point pt>y ! |
||
.pt \ 6 7</ |
.pt \ 6 7</syntaxhighlight> |
||
{{works with|GNU Forth|0.6.2}} |
{{works with|GNU Forth|0.6.2}} |
||
Some Forths have mechanisms for declaring complex structures. For example, GNU Forth uses this syntax: |
Some Forths have mechanisms for declaring complex structures. For example, GNU Forth uses this syntax: |
||
< |
<syntaxhighlight lang="forth">struct |
||
cell% field pt>x |
cell% field pt>x |
||
cell% field pt>y |
cell% field pt>y |
||
end-struct point%</ |
end-struct point%</syntaxhighlight> |
||
=={{header|Fortran}}== |
=={{header|Fortran}}== |
||
In ISO Fortran 90 or later, use a TYPE declaration, "constructor" syntax, and field delimiter syntax: |
In ISO Fortran 90 or later, use a TYPE declaration, "constructor" syntax, and field delimiter syntax: |
||
< |
<syntaxhighlight lang="fortran">program typedemo |
||
type rational ! Type declaration |
type rational ! Type declaration |
||
integer :: numerator |
integer :: numerator |
||
Line 458: | Line 934: | ||
oon_denoms = one_over_n%denominator ! Access denominator field in every |
oon_denoms = one_over_n%denominator ! Access denominator field in every |
||
! rational array element & store |
! rational array element & store |
||
end program typedemo ! as integer array</ |
end program typedemo ! as integer array</syntaxhighlight> |
||
=={{header| |
=={{header|FreeBASIC}}== |
||
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64 |
|||
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 } |
|||
Type Point |
|||
let points = [ |
|||
As Integer x, y |
|||
End Type |
|||
{x = 5; y = 5} ] |
|||
Seq.iter (fun p -> printfn "%d,%d" p.x p.y) points</lang> |
|||
=={{header|Go}}== |
|||
<lang go>package main |
|||
Dim p As Point = (1, 2) |
|||
import "fmt" |
|||
Dim p2 As Point = (3, 4) |
|||
Print p.x, p.y |
|||
Print p2.x, p2.y |
|||
Sleep</syntaxhighlight> |
|||
{{out}} |
|||
type point struct { |
|||
<pre> |
|||
1 2 |
|||
3 4 |
|||
</pre> |
|||
=={{header|FutureBasic}}== |
|||
<syntaxhighlight lang="futurebasic"> |
|||
CGRect r = {0, 0, 250, 100} |
|||
printf @"x = %.f : y = %.f : width = %.f : height = %.f", r.origin.x, r.origin.y, r.size.width, r.size.height |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
{{output}} |
|||
<pre> |
|||
x = 0 : y = 0 : width = 250 : height = 100 |
|||
</pre> |
|||
=={{header|Go}}== |
|||
<syntaxhighlight lang="go">type point struct { |
|||
x, y float64 |
x, y float64 |
||
} |
} |
||
</syntaxhighlight> |
|||
func main() { |
|||
fmt.Println(point{3, 4}) |
|||
}</lang> |
|||
=={{header|Groovy}}== |
=={{header|Groovy}}== |
||
===Declaration=== |
===Declaration=== |
||
< |
<syntaxhighlight lang="groovy">class Point { |
||
int x |
int x |
||
int y |
int y |
||
Line 492: | Line 985: | ||
Point(int x = 0, int y = 0) { this.x = x; this.y = y } |
Point(int x = 0, int y = 0) { this.x = x; this.y = y } |
||
String toString() { "{x:${x}, y:${y}}" } |
String toString() { "{x:${x}, y:${y}}" } |
||
}</ |
}</syntaxhighlight> |
||
===Instantiation=== |
===Instantiation=== |
||
=====Direct===== |
=====Direct===== |
||
< |
<syntaxhighlight lang="groovy">// Default Construction with explicit property setting: |
||
def p0 = new Point() |
def p0 = new Point() |
||
assert 0 == p0.x |
assert 0 == p0.x |
||
Line 512: | Line 1,005: | ||
def p2 = new Point(36) |
def p2 = new Point(36) |
||
assert 36 == p2.x |
assert 36 == p2.x |
||
assert 0 == p2.y</ |
assert 0 == p2.y</syntaxhighlight> |
||
=====List-to-argument Substitution===== |
=====List-to-argument Substitution===== |
||
There are several ways that a List can be substituted for constructor arguments via "type coercion" (casting). |
There are several ways that a List can be substituted for constructor arguments via "type coercion" (casting). |
||
< |
<syntaxhighlight lang="groovy">// Explicit coersion from list with "as" keyword |
||
def p4 = [36, -2] as Point |
def p4 = [36, -2] as Point |
||
assert 36 == p4.x |
assert 36 == p4.x |
||
Line 534: | Line 1,027: | ||
Point p8 = [36] |
Point p8 = [36] |
||
assert 36 == p8.x |
assert 36 == p8.x |
||
assert 0 == p8.y</ |
assert 0 == p8.y</syntaxhighlight> |
||
=====Map-to-property Substitution===== |
=====Map-to-property Substitution===== |
||
There are several ways to construct an object using a map (or a comma-separated list of map entries) that substitutes entries for class properties. The process is properly (A) instantiation, followed by (B) property mapping. Because the instantiation is not tied to the mapping, it requires the existence of a no-argument constructor. |
There are several ways to construct an object using a map (or a comma-separated list of map entries) that substitutes entries for class properties. The process is properly (A) instantiation, followed by (B) property mapping. Because the instantiation is not tied to the mapping, it requires the existence of a no-argument constructor. |
||
< |
<syntaxhighlight lang="groovy">// Direct map-based construction |
||
def p3 = new Point([x: 36, y: -2]) |
def p3 = new Point([x: 36, y: -2]) |
||
assert 36 == p3.x |
assert 36 == p3.x |
||
Line 568: | Line 1,061: | ||
Point p9 = [y:-2] |
Point p9 = [y:-2] |
||
assert 0 == p9.x |
assert 0 == p9.x |
||
assert -2 == p9.y</ |
assert -2 == p9.y</syntaxhighlight> |
||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
Line 608: | Line 1,101: | ||
You can make a tuple literal by using a comma-delimited list surrounded by parentheses, without needing to declare the type first: |
You can make a tuple literal by using a comma-delimited list surrounded by parentheses, without needing to declare the type first: |
||
< |
<syntaxhighlight lang="haskell">p = (2,3)</syntaxhighlight> |
||
The type of <code>p</code> is <code>(Int, Int)</code>, using the same comma-delimited list syntax as the literal. |
The type of <code>p</code> is <code>(Int, Int)</code>, using the same comma-delimited list syntax as the literal. |
||
Line 623: | Line 1,116: | ||
=={{header|Icon}} and {{header|Unicon}}== |
=={{header|Icon}} and {{header|Unicon}}== |
||
<lang |
<syntaxhighlight lang="icon">record Point(x,y)</syntaxhighlight> |
||
=={{header|IDL}}== |
=={{header|IDL}}== |
||
< |
<syntaxhighlight lang="idl">point = {x: 6 , y: 0 } |
||
point.y = 7 |
point.y = 7 |
||
print, point |
print, point |
||
;=> { 6 7}</ |
;=> { 6 7}</syntaxhighlight> |
||
=={{header|J}}== |
=={{header|J}}== |
||
Line 637: | Line 1,129: | ||
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: |
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: |
||
< |
<syntaxhighlight lang="j"> NB. Create a "Point" class |
||
coclass'Point' |
coclass'Point' |
||
NB. Define its |
NB. Define its constructor |
||
create =: 3 : 0 |
create =: 3 : 0 |
||
'X Y' =: y |
'X Y' =: y |
||
Line 653: | Line 1,145: | ||
10 |
10 |
||
Y__P |
Y__P |
||
20</ |
20</syntaxhighlight> |
||
=={{header|Jakt}}== |
|||
<syntaxhighlight lang="jakt"> |
|||
struct Point { |
|||
x: i64 |
|||
y: i64 |
|||
} |
|||
fn main() { |
|||
println("{}", Point(x: 3, y: 4)) |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|Java}}== |
=={{header|Java}}== |
||
Starting with Java 14 you can use a record |
|||
<syntaxhighlight lang="java"> |
|||
record Point(int x, int y) { } |
|||
</syntaxhighlight> |
|||
Usage |
|||
<syntaxhighlight lang="java"> |
|||
Point point = new Point(1, 2); |
|||
int x = point.x; |
|||
int y = point.y; |
|||
</syntaxhighlight> |
|||
<br /> |
|||
Alternately |
|||
We use a class: |
We use a class: |
||
< |
<syntaxhighlight lang="java">public class Point |
||
{ |
{ |
||
public int x, y; |
public int x, y; |
||
Line 670: | Line 1,186: | ||
System.out.println("y = " + point.y ); |
System.out.println("y = " + point.y ); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
<lang |
<syntaxhighlight lang="javascript">//using object literal syntax |
||
var point = {x : 1, y : 2}; |
|||
//using constructor |
|||
var Point = function (x, y) { |
|||
this.x = x; |
|||
this.y = y; |
|||
}; |
|||
point = new Point(1, 2); |
|||
//using ES6 class syntax |
|||
class Point { |
|||
constructor(x, y) { |
|||
this.x = x; |
|||
this.y = y; |
|||
} |
|||
} |
|||
point = new Point(1, 2);</syntaxhighlight> |
|||
=={{header|jq}}== |
|||
<syntaxhighlight lang="jq">{"x":1, "y":2}</syntaxhighlight> |
|||
If the emphasis in the task description is on "type", then an alternative approach would be to include a "type" key, e.g. |
|||
<syntaxhighlight lang="jq">{"x":1, "y":2, type: "Point"}</syntaxhighlight> |
|||
Using this approach, one can distinguish between objects of type "Point" and those that happen to have keys named "x" and "y". |
|||
=={{header|JSON}}== |
=={{header|JSON}}== |
||
< |
<syntaxhighlight lang="json">{"x":1,"y":2}</syntaxhighlight> |
||
=={{header|Julia}}== |
|||
'''Define the type''': |
|||
<syntaxhighlight lang="julia">struct Point{T<:Real} |
|||
x::T |
|||
y::T |
|||
end</syntaxhighlight> |
|||
The components of <code>Point</code> can be any sort of real number, though they do have to be of the same type. |
|||
'''Define a few simple operations for Point''': |
|||
<syntaxhighlight lang="julia">Base.:(==)(u::Point, v::Point) = u.x == v.x && u.y == v.y |
|||
Base.:-(u::Point) = Point(-u.x, -u.y) |
|||
Base.:+(u::Point, v::Point) = Point(u.x + v.x, u.y + v.y) |
|||
Base.:-(u::Point, v::Point) = u + (-v)</syntaxhighlight> |
|||
'''Have fun''': |
|||
<syntaxhighlight lang="julia">a, b, c = Point(1, 2), Point(3, 7), Point(2, 4) |
|||
@show a b c |
|||
@show a + b |
|||
@show -a + b |
|||
@show a - b |
|||
@show a + b + c |
|||
@show a == b |
|||
@show a + a == c</syntaxhighlight> |
|||
{{out}} |
|||
<pre>a = Point{Int64}(1, 2) |
|||
b = Point{Int64}(3, 7) |
|||
c = Point{Int64}(2, 4) |
|||
a + b = Point{Int64}(4, 9) |
|||
-a + b = Point{Int64}(2, 5) |
|||
a - b = Point{Int64}(-2, -5) |
|||
a + b + c = Point{Int64}(6, 13) |
|||
a == b = false |
|||
a + a == c = true</pre> |
|||
=={{header|KonsolScript}}== |
=={{header|KonsolScript}}== |
||
< |
<syntaxhighlight lang="konsolscript">Var:Create( |
||
Point, |
Point, |
||
Number x, |
Number x, |
||
Number y |
Number y |
||
)</ |
)</syntaxhighlight> |
||
Instanciate it with... |
Instanciate it with... |
||
< |
<syntaxhighlight lang="konsolscript">function main() { |
||
Var:Point point; |
Var:Point point; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Kotlin}}== |
|||
<syntaxhighlight lang="scala">data class Point(var x: Int, var y: Int) |
|||
fun main(args: Array<String>) { |
|||
val p = Point(1, 2) |
|||
println(p) |
|||
p.x = 3 |
|||
p.y = 4 |
|||
println(p) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Point(x=1, y=2) |
|||
Point(x=3, y=4) |
|||
</pre> |
|||
=={{header|Lambdatalk}}== |
|||
<syntaxhighlight lang="scheme"> |
|||
1) a pair |
|||
{def P {P.new 1 2}} |
|||
-> P |
|||
{P.left {P}} |
|||
-> 1 |
|||
{P.right {P}} |
|||
-> 2 |
|||
2) its Lispsish variant |
|||
{def Q {cons 1 2}} |
|||
-> Q |
|||
{car {Q}} |
|||
-> 1 |
|||
{cdr {Q}} |
|||
-> 2 |
|||
3) as an array |
|||
{def R {A.new 1 2}} |
|||
-> R |
|||
{A.first {R}} |
|||
-> 1 |
|||
{A.last {R}} |
|||
-> 2 |
|||
</syntaxhighlight> |
|||
=={{header|Lang}}== |
|||
<syntaxhighlight lang="lang"> |
|||
&Point = { |
|||
$x |
|||
$y |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|Lasso}}== |
|||
In Lasso, a point could just be stored in the pair type. However, assuming we want to be able to access the points using the member methods [Point->x] and [Point->y], let's just create a type that inherits from the pair type: |
|||
<syntaxhighlight lang="lasso">define Point => type { |
|||
parent pair |
|||
public onCreate(x,y) => { |
|||
..onCreate(#x=#y) |
|||
} |
|||
public x => .first |
|||
public y => .second |
|||
} |
|||
local(point) = Point(33, 42) |
|||
#point->x |
|||
#point->y</syntaxhighlight> |
|||
{{out}} |
|||
<pre>33 |
|||
43</pre> |
|||
=={{header|LFE}}== |
|||
Simply define a record in the LFE REPL (can also be used in include files, modules, etc.): |
|||
<syntaxhighlight lang="lisp"> |
|||
(defrecord point |
|||
x |
|||
y) |
|||
</syntaxhighlight> |
|||
Creating points: |
|||
<pre> |
|||
> (make-point x 0 y 0) |
|||
#(point 0 0) |
|||
> (set p (make-point x 1.1 y -4.2)) |
|||
#(point 1.1 -4.2) |
|||
</pre> |
|||
Accessing: |
|||
<pre> |
|||
> (point-x p) |
|||
1.1 |
|||
> (point-y p) |
|||
-4.2 |
|||
</pre> |
|||
Updates (note that since LFE has no mutable data, persisted updates would need to rebind the new value to the old variable name): |
|||
<pre> |
|||
> (set-point-x p 3.1) |
|||
#(point 3.1 -4.2) |
|||
> (set-point-y p 4.2) |
|||
#(point 1.1 4.2) |
|||
</pre> |
|||
Metadata, etc.: |
|||
<pre> |
|||
> (fields-point) |
|||
(x y) |
|||
> (is-point #(x y)) |
|||
false |
|||
> (is-point p) |
|||
true |
|||
</pre> |
|||
=={{header|Lingo}}== |
|||
Point and Vector types are built-in. A custom "MyPoint" type can be implemented like this: |
|||
<syntaxhighlight lang="lingo">-- parent script "MyPoint" |
|||
property x |
|||
property y |
|||
on new (me, px, py) |
|||
me.x = px |
|||
me.y = py |
|||
return me |
|||
end</syntaxhighlight> |
|||
<syntaxhighlight lang="lingo">p = script("MyPoint").new(23, 42) |
|||
put p.x, p.y |
|||
-- 23 42</syntaxhighlight> |
|||
Construction could also be simplified by using a global wrapper function: |
|||
<syntaxhighlight lang="lingo">-- in some movie script |
|||
on MyPoint (x, y) |
|||
return script("MyPoint").new(x, y) |
|||
end</syntaxhighlight> |
|||
<syntaxhighlight lang="lingo">p = MyPoint(23, 42) |
|||
put p.x, p.y |
|||
-- 23 42</syntaxhighlight> |
|||
=={{header|Logo}}== |
=={{header|Logo}}== |
||
In Logo, a point is represented by a list of two numbers. For example, this will draw a triangle: |
In Logo, a point is represented by a list of two numbers. For example, this will draw a triangle: |
||
< |
<syntaxhighlight lang="logo">setpos [100 100] setpos [100 0] setpos [0 0] |
||
show pos ; [0 0]</ |
show pos ; [0 0]</syntaxhighlight> |
||
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: |
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: |
||
< |
<syntaxhighlight lang="logo">until [(first mousepos) < 0] [ifelse button? [pendown] [penup] setpos mousepos]</syntaxhighlight> |
||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
Line 705: | Line 1,424: | ||
Lua could use a simple table to store a compound data type Point(x, y): |
Lua could use a simple table to store a compound data type Point(x, y): |
||
< |
<syntaxhighlight lang="lua"> |
||
a = {x = 1; y = 2} |
a = {x = 1; y = 2} |
||
b = {x = 3; y = 4} |
b = {x = 3; y = 4} |
||
Line 714: | Line 1,433: | ||
print(a.x, a.y) --> 1 2 |
print(a.x, a.y) --> 1 2 |
||
print(c.x, c.y) --> 4 6 |
print(c.x, c.y) --> 4 6 |
||
</syntaxhighlight> |
|||
</lang> |
|||
==== Prototype Object ==== |
==== Prototype Object ==== |
||
Furthermore, Lua could create a prototype object (OOP class emulation) to represent a compound data type Point(x, y) as the following: |
Furthermore, Lua could create a prototype object (OOP class emulation) to represent a compound data type Point(x, y) as the following: |
||
< |
<syntaxhighlight lang="lua"> |
||
cPoint = {} -- metatable (behaviour table) |
cPoint = {} -- metatable (behaviour table) |
||
function newPoint(x, y) -- constructor |
function newPoint(x, y) -- constructor |
||
Line 729: | Line 1,448: | ||
return setmetatable(pointPrototype, cPoint) -- set behaviour and return the pointPrototype |
return setmetatable(pointPrototype, cPoint) -- set behaviour and return the pointPrototype |
||
end--newPoint |
end--newPoint |
||
</syntaxhighlight> |
|||
</lang> |
|||
In the above example, the methods are declared inside the constructor so that they could access the closured values <code>x</code> and <code>y</code> (see usage example). The <code>pointPrototype:type</code> method could be used to extend the original <code>type</code> function available in Lua: |
In the above example, the methods are declared inside the constructor so that they could access the closured values <code>x</code> and <code>y</code> (see usage example). The <code>pointPrototype:type</code> method could be used to extend the original <code>type</code> function available in Lua: |
||
< |
<syntaxhighlight lang="lua"> |
||
local oldtype = type; -- store original type function |
local oldtype = type; -- store original type function |
||
function type(v) |
function type(v) |
||
Line 743: | Line 1,462: | ||
end--if vType=="table" |
end--if vType=="table" |
||
end--type |
end--type |
||
</syntaxhighlight> |
|||
</lang> |
|||
The usage of metatable <code>cPoint</code> which stores the behavior of the <code>pointPrototype</code> enables additional behaviour to be added to the data type, such as: |
The usage of metatable <code>cPoint</code> which stores the behavior of the <code>pointPrototype</code> enables additional behaviour to be added to the data type, such as: |
||
< |
<syntaxhighlight lang="lua"> |
||
function cPoint.__add(op1, op2) -- add the x and y components |
function cPoint.__add(op1, op2) -- add the x and y components |
||
if type(op1)=="point" and type(op2)=="point" then |
if type(op1)=="point" and type(op2)=="point" then |
||
Line 762: | Line 1,481: | ||
end--if type(op1) |
end--if type(op1) |
||
end--cPoint.__sub |
end--cPoint.__sub |
||
</syntaxhighlight> |
|||
</lang> |
|||
Usage example: |
Usage example: |
||
< |
<syntaxhighlight lang="lua"> |
||
a = newPoint(1, 2) |
a = newPoint(1, 2) |
||
b = newPoint(3, 4) |
b = newPoint(3, 4) |
||
Line 774: | Line 1,493: | ||
print(c:getXY()) --> 4 6 |
print(c:getXY()) --> 4 6 |
||
print((a-b):getXY()) --> -2 -2 -- using __sub behaviour |
print((a-b):getXY()) --> -2 -2 -- using __sub behaviour |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header| |
=={{header|Maple}}== |
||
<syntaxhighlight lang="maple">Point:= Record(x = 2,y = 4): |
|||
Point:-x; |
|||
Point:-y;</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
2 |
|||
4 |
|||
</pre> |
|||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
|||
Expressions like point[x, y] can be used without defining. |
Expressions like point[x, y] can be used without defining. |
||
< |
<syntaxhighlight lang="mathematica">In[1]:= a = point[2, 3] |
||
Out[1]= point[2, 3] |
Out[1]= point[2, 3] |
||
Line 788: | Line 1,518: | ||
In[3]:= a[[2]] = 4; a |
In[3]:= a[[2]] = 4; a |
||
Out[3]= point[2, 4]</ |
Out[3]= point[2, 4]</syntaxhighlight> |
||
Or you can just define a function. |
Or you can just define a function. |
||
< |
<syntaxhighlight lang="mathematica">p[x] = 2; p[y] = 3;</syntaxhighlight> |
||
Data will be stored as down values of the symbol ''p''. |
Data will be stored as down values of the symbol ''p''. |
||
=={{header|MATLAB}} / {{header|Octave}}== |
=={{header|MATLAB}} / {{header|Octave}}== |
||
< |
<syntaxhighlight lang="matlab"> point.x=3; |
||
point.y=4;</ |
point.y=4;</syntaxhighlight> |
||
Alternatively, coordinates can be also stored as vectors |
Alternatively, coordinates can be also stored as vectors |
||
< |
<syntaxhighlight lang="matlab"> point = [3,4];</syntaxhighlight> |
||
=={{header|Maxima}}== |
=={{header|Maxima}}== |
||
< |
<syntaxhighlight lang="maxima">defstruct(point(x, y))$ |
||
p: new(point)$ |
p: new(point)$ |
||
Line 809: | Line 1,538: | ||
q: point(1, 2)$ |
q: point(1, 2)$ |
||
p@x: 5$</ |
p@x: 5$</syntaxhighlight> |
||
=={{header|MAXScript}}== |
=={{header|MAXScript}}== |
||
Point is a built-in object type in MAX, so... |
Point is a built-in object type in MAX, so... |
||
< |
<syntaxhighlight lang="maxscript">struct myPoint (x, y) |
||
newPoint = myPoint x:3 y:4</ |
newPoint = myPoint x:3 y:4</syntaxhighlight> |
||
In practice however, you'd use MAX's built in Point2 type |
In practice however, you'd use MAX's built in Point2 type |
||
< |
<syntaxhighlight lang="maxscript">newPoint = Point2 3 4</syntaxhighlight> |
||
=={{header|MiniScript}}== |
|||
<syntaxhighlight lang="miniscript">Point = {} |
|||
Point.x = 0 |
|||
Point.y = 0</syntaxhighlight> |
|||
=={{header|Modula-2}}== |
=={{header|Modula-2}}== |
||
< |
<syntaxhighlight lang="modula2">TYPE Point = RECORD |
||
x, y : INTEGER |
x, y : INTEGER |
||
END;</ |
END;</syntaxhighlight> |
||
Usage: |
Usage: |
||
< |
<syntaxhighlight lang="modula2">VAR point : Point; |
||
... |
... |
||
point.x := 12; |
point.x := 12; |
||
point.y := 7;</ |
point.y := 7;</syntaxhighlight> |
||
=={{header|Modula-3}}== |
=={{header|Modula-3}}== |
||
< |
<syntaxhighlight lang="modula3">TYPE Point = RECORD |
||
x, y: INTEGER; |
x, y: INTEGER; |
||
END;</ |
END;</syntaxhighlight> |
||
Usage: |
Usage: |
||
Line 849: | Line 1,583: | ||
=={{header|NetRexx}}== |
=={{header|NetRexx}}== |
||
Like Java, NetRexx uses the <tt>class</tt> instruction to create compound types. Unlike Java; NetRexx provides keywords to automatically generate getters and setters for <tt>class</tt> properties and will automatically generate intermediate methods based on defaults provided in method prototypes. |
Like Java, NetRexx uses the <tt>class</tt> instruction to create compound types. Unlike Java; NetRexx provides keywords to automatically generate getters and setters for <tt>class</tt> properties and will automatically generate intermediate methods based on defaults provided in method prototypes. |
||
< |
<syntaxhighlight lang="netrexx">/* NetRexx */ |
||
options replace format comments java crossref symbols nobinary |
options replace format comments java crossref symbols nobinary |
||
Line 871: | Line 1,605: | ||
res = 'X='getX()',Y='getY() |
res = 'X='getX()',Y='getY() |
||
return res |
return res |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
|||
'''Output:''' |
|||
<pre> |
<pre> |
||
X=2,Y=4 |
X=2,Y=4 |
||
</pre> |
</pre> |
||
=={{header|Nim}}== |
|||
<syntaxhighlight lang="nim">type Point = tuple[x, y: int] |
|||
var p: Point = (12, 13) |
|||
var p2: Point = (x: 100, y: 200)</syntaxhighlight> |
|||
=={{header|Oberon-2}}== |
|||
<syntaxhighlight lang="oberon2"> |
|||
MODULE Point; |
|||
TYPE |
|||
Object* = POINTER TO ObjectDesc; |
|||
ObjectDesc* = RECORD |
|||
x-,y-: INTEGER; |
|||
END; |
|||
PROCEDURE (p: Object) Init(x,y: INTEGER); |
|||
BEGIN |
|||
p.x := x; p.y := y |
|||
END Init; |
|||
PROCEDURE New*(x,y: INTEGER): Object; |
|||
VAR |
|||
p: Object; |
|||
BEGIN |
|||
NEW(p);p.Init(x,y);RETURN p; |
|||
END New; |
|||
END Point. |
|||
</syntaxhighlight> |
|||
=={{header|Objeck}}== |
=={{header|Objeck}}== |
||
Classes are used for compound data types. |
Classes are used for compound data types. |
||
< |
<syntaxhighlight lang="objeck"> |
||
class Point { |
class Point { |
||
@x : Int; |
@x : Int; |
||
Line 915: | Line 1,679: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
===Algebraic Data Type=== |
===Algebraic Data Type=== |
||
See [[wp:Algebraic_data_type|algebraic data type]]. The different options ("Empty", "Leaf", "Node") are called ''constructors'', and is associated with 0 or |
See [[wp:Algebraic_data_type|algebraic data type]]. The different options ("Empty", "Leaf", "Node") are called ''constructors'', and is associated with 0 or more arguments with the declared types; multiple arguments are declared with a syntax that looks like a tuple type, but it is not really a tuple. |
||
< |
<syntaxhighlight lang="ocaml">type tree = Empty |
||
| Leaf of int |
| Leaf of int |
||
| Node of tree * tree |
| Node of tree * tree |
||
let t1 = Node (Leaf 1, Node (Leaf 2, Leaf 3))</ |
let t1 = Node (Leaf 1, Node (Leaf 2, Leaf 3))</syntaxhighlight> |
||
===Record Type=== |
===Record Type=== |
||
< |
<syntaxhighlight lang="ocaml">type point = { x : int; y : int }</syntaxhighlight> |
||
How to construct a point: |
How to construct a point: |
||
< |
<syntaxhighlight lang="ocaml">let p = { x = 4; y = 5 }</syntaxhighlight> |
||
You can use the dot (".") to access fields. |
You can use the dot (".") to access fields. |
||
< |
<syntaxhighlight lang="ocaml">p.x (* evaluates to 4 *)</syntaxhighlight> |
||
Fields can be optionally declared to be mutable: |
Fields can be optionally declared to be mutable: |
||
< |
<syntaxhighlight lang="ocaml">type mutable_point = { mutable x2 : int; mutable y2 : int }</syntaxhighlight> |
||
Then they can be assigned using the assignment operator "<-" |
Then they can be assigned using the assignment operator "<-" |
||
< |
<syntaxhighlight lang="ocaml">let p2 = { x2 = 4; y2 = 5 } in |
||
p2.x2 <- 6; |
p2.x2 <- 6; |
||
p2 (* evaluates to { x2 = 6; y2 = 5 } *)</ |
p2 (* evaluates to { x2 = 6; y2 = 5 } *)</syntaxhighlight> |
||
===Tuple Type=== |
===Tuple Type=== |
||
Line 951: | Line 1,715: | ||
You can make a tuple literal by using a comma-delimited list, optionally surrounded by parentheses, without needing to declare the type first: |
You can make a tuple literal by using a comma-delimited list, optionally surrounded by parentheses, without needing to declare the type first: |
||
< |
<syntaxhighlight lang="ocaml">let p = (2,3)</syntaxhighlight> |
||
The type of <code>p</code> is a product (indicated by <code>*</code>) of the types of the components: |
The type of <code>p</code> is a product (indicated by <code>*</code>) of the types of the components: |
||
# let p = (2,3);; |
# let p = (2,3);; |
||
val p : int * int = (2, 3) |
val p : int * int = (2, 3) |
||
=={{header|Oforth}}== |
|||
Using a class : |
|||
<syntaxhighlight lang="oforth">Object Class new: Point(x, y)</syntaxhighlight> |
|||
=={{header|ooRexx}}== |
=={{header|ooRexx}}== |
||
ooRexx uses class for compound data types. |
ooRexx uses class for compound data types. |
||
<syntaxhighlight lang="oorexx"> |
|||
<lang ooRexx> |
|||
p = .point~new(3,4) |
p = .point~new(3,4) |
||
say "x =" p~x |
say "x =" p~x |
||
Line 971: | Line 1,741: | ||
::attribute x |
::attribute x |
||
::attribute y |
::attribute y |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|OpenEdge/Progress}}== |
=={{header|OpenEdge/Progress}}== |
||
Line 977: | Line 1,747: | ||
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. |
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. |
||
< |
<syntaxhighlight lang="progress (openedge abl)">def temp-table point |
||
field x as int |
field x as int |
||
field y as int |
field y as int |
||
.</ |
.</syntaxhighlight> |
||
Another option would be a simple class. |
Another option would be a simple class. |
||
=={{header|OxygenBasic}}== |
=={{header|OxygenBasic}}== |
||
< |
<syntaxhighlight lang="oxygenbasic"> |
||
'SHORT FORM |
'SHORT FORM |
||
type point float x,y |
type point float x,y |
||
'FULL FORM |
'FULL FORM |
||
type point |
type point |
||
Line 994: | Line 1,764: | ||
float y |
float y |
||
end type |
end type |
||
</lang> |
|||
point p |
|||
'WITH DEFAULT VALUES |
|||
type point |
|||
float x = 1.0 |
|||
float y = 1.0 |
|||
end type |
|||
point p = {} 'assigns the set of default values |
|||
print p.x " " p.y |
|||
</syntaxhighlight> |
|||
=={{header|Oz}}== |
=={{header|Oz}}== |
||
A point can be represented by using a record value: |
A point can be represented by using a record value: |
||
< |
<syntaxhighlight lang="oz">P = point(x:1 y:2)</syntaxhighlight> |
||
Now we can access the components by name: P.x and P.y |
Now we can access the components by name: P.x and P.y |
||
Often such values are deconstructed by pattern matching: |
Often such values are deconstructed by pattern matching: |
||
< |
<syntaxhighlight lang="oz">case P of point(x:X y:Y) then |
||
{Show X} |
{Show X} |
||
{Show Y} |
{Show Y} |
||
end</ |
end</syntaxhighlight> |
||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
< |
<syntaxhighlight lang="parigp">point.x=1; |
||
point.y=2;</ |
point.y=2;</syntaxhighlight> |
||
=={{header|Pascal}}== |
=={{header|Pascal}}== |
||
< |
<syntaxhighlight lang="pascal">type point = record |
||
x, y: integer; |
x, y: integer; |
||
end;</ |
end;</syntaxhighlight> |
||
=={{header|PascalABC.NET}}== |
|||
Classes in PascalABC.NET are reference types and records are value types. |
|||
<syntaxhighlight lang="pascal"> |
|||
type |
|||
Point = class |
|||
x,y: integer; |
|||
constructor(x,y: integer) := (Self.x,Self.y) := (x,y); |
|||
end; |
|||
PointRec = record |
|||
x,y: integer; |
|||
constructor(x,y: integer) := (Self.x,Self.y) := (x,y); |
|||
end; |
|||
begin |
|||
var p := new Point(2,3); |
|||
Println(p.x,p.y); |
|||
var pr := new PointRec(4,5); |
|||
Println(pr.x,pr.y); |
|||
end. |
|||
</syntaxhighlight> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
===Array=== |
===Array=== |
||
< |
<syntaxhighlight lang="perl">my @point = (3, 8);</syntaxhighlight> |
||
===Hash=== |
===Hash=== |
||
< |
<syntaxhighlight lang="perl">my %point = ( |
||
x => 3, |
x => 3, |
||
y => 8 |
y => 8 |
||
);</ |
);</syntaxhighlight> |
||
===Class instance=== |
===Class instance=== |
||
< |
<syntaxhighlight lang="perl">package Point; |
||
use strict; |
use strict; |
||
Line 1,036: | Line 1,840: | ||
; |
; |
||
my $point = Point->new(x => 3, y => 8);</ |
my $point = Point->new(x => 3, y => 8);</syntaxhighlight> |
||
=={{header| |
=={{header|Phix}}== |
||
===traditional user defined type=== |
|||
{{works with|Rakudo|#24 "Seoul"}} |
|||
The sequence is a natural compound data type. The following would be the same without the type point and declaring p as a sequence, apart from the run-time error. There would be no difficulty defining point to have a string and two atoms. |
|||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
|||
<span style="color: #008080;">enum</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span> |
|||
<span style="color: #008080;">type</span> <span style="color: #000000;">point</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">y</span> <span style="color: #008080;">and</span> <span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">and</span> <span style="color: #004080;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">])</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">type</span> |
|||
<span style="color: #000000;">point</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">175</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3.375</span><span style="color: #0000FF;">}</span> |
|||
<span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">20</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"point p is "</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">p</span> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"p[x]:%g, p[y]:%g\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">],</span><span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">]})</span> |
|||
<span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- fine</span> |
|||
<span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"string"</span> <span style="color: #000080;font-style:italic;">-- run-time error (not pwa/p2js)</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
|||
<pre> |
|||
point p is {107.5,3.375} |
|||
p[x]:107.5, p[y]:3.375 |
|||
C:\Program Files (x86)\Phix\test.exw:12 |
|||
===Array=== |
|||
type check failure, p is {0,"string"} |
|||
<lang perl6>my @point = 3, 8;</lang> |
|||
--> see C:\Program Files (x86)\Phix\ex.err |
|||
===Hash=== |
|||
Press Enter... |
|||
<lang perl6>my %point = x => 3, y => 8;</lang> |
|||
</pre> |
|||
=== |
===classes=== |
||
{{libheader|Phix/Class}} |
|||
<lang perl6>class Point { has $.x is rw; has $.y is rw; } |
|||
You could also use a class (not pwa/p2js) |
|||
my Point $point .= new(x => 3, y => 8);</lang> |
|||
<!--<syntaxhighlight lang="phix">--> |
|||
<span style="color: #008080;">class</span> <span style="color: #000000;">point</span> |
|||
<span style="color: #008080;">public</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">class</span> |
|||
<span style="color: #000000;">point</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new</span><span style="color: #0000FF;">({</span><span style="color: #000000;">175</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3.375</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #000000;">p</span><span style="color: #0000FF;">.</span><span style="color: #000000;">x</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">.</span><span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #000000;">20</span> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"p.x:%g, p.y:%g\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">p</span><span style="color: #0000FF;">.</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">.</span><span style="color: #000000;">y</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #000000;">p</span><span style="color: #0000FF;">.</span><span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- fine</span> |
|||
<span style="color: #000000;">p</span><span style="color: #0000FF;">.</span><span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"string"</span> <span style="color: #000080;font-style:italic;">-- run-time error</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
|||
<pre> |
|||
p.x:107.5, p.y:3.375 |
|||
C:\Program Files (x86)\Phix\test.exw:9 |
|||
type error assigning "string" to point.y |
|||
--> see C:\Program Files (x86)\Phix\ex.err |
|||
Press Enter... |
|||
</pre> |
|||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
< |
<syntaxhighlight lang="php"># Using pack/unpack |
||
$point = pack("ii", 1, 2); |
$point = pack("ii", 1, 2); |
||
Line 1,062: | Line 1,908: | ||
list($x,$y) = unpack("ii", $point); |
list($x,$y) = unpack("ii", $point); |
||
echo $x; |
echo $x; |
||
echo $y;</ |
echo $y;</syntaxhighlight> |
||
< |
<syntaxhighlight lang="php"># Using array |
||
$point = array('x' => 1, 'y' => 2); |
$point = array('x' => 1, 'y' => 2); |
||
Line 1,071: | Line 1,917: | ||
# or simply: |
# or simply: |
||
echo $point['x'], ' ', $point['y'], "\n";</ |
echo $point['x'], ' ', $point['y'], "\n";</syntaxhighlight> |
||
< |
<syntaxhighlight lang="php"># Using class |
||
class Point { |
class Point { |
||
function __construct($x, $y) { $this->x = $x; $this->y = $y; } |
function __construct($x, $y) { $this->x = $x; $this->y = $y; } |
||
Line 1,079: | Line 1,925: | ||
} |
} |
||
$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.</ |
echo $point; # will call __tostring() in later releases of PHP 5.2; before that, it won't work so good.</syntaxhighlight> |
||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
< |
<syntaxhighlight lang="picolisp">(class +Point) |
||
(dm T (X Y) |
(dm T (X Y) |
||
Line 1,090: | Line 1,936: | ||
(setq P (new '(+Point) 3 4)) |
(setq P (new '(+Point) 3 4)) |
||
(show P)</ |
(show P)</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre>$52717735311266 (+Point) |
<pre>$52717735311266 (+Point) |
||
y 4 |
y 4 |
||
x 3</pre> |
x 3</pre> |
||
=={{header|Pike}}== |
|||
<syntaxhighlight lang="pike"> |
|||
class Point { |
|||
int x, y; |
|||
void create(int _x, int _y) |
|||
{ |
|||
x = _x; |
|||
y = _y; |
|||
} |
|||
} |
|||
void main() |
|||
{ |
|||
object point = Point(10, 20); |
|||
write("%d %d\n", point->x, point->y); |
|||
} |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
10 20 |
|||
</pre> |
|||
=={{header|PL/I}}== |
=={{header|PL/I}}== |
||
<syntaxhighlight lang="pl/i"> |
|||
<lang PL/I> |
|||
define structure |
define structure |
||
1 point, |
1 point, |
||
Line 1,104: | Line 1,972: | ||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Plain English}}== |
|||
<syntaxhighlight lang="plainenglish">A cartesian point is a record with an x coord and a y coord.</syntaxhighlight> |
|||
=={{header|Pop11}}== |
=={{header|Pop11}}== |
||
< |
<syntaxhighlight lang="pop11">uses objectclass; |
||
define :class Point; |
define :class Point; |
||
slot x = 0; |
slot x = 0; |
||
slot y = 0; |
slot y = 0; |
||
enddefine;</ |
enddefine;</syntaxhighlight> |
||
=={{header| |
=={{header|PowerShell}}== |
||
{{works with|PowerShell|5}} |
|||
<syntaxhighlight lang="powershell"> |
|||
class Point { |
|||
[Int]$a |
|||
[Int]$b |
|||
Point() { |
|||
$this.a = 0 |
|||
$this.b = 0 |
|||
} |
|||
Point([Int]$a, [Int]$b) { |
|||
$this.a = $a |
|||
$this.b = $b |
|||
} |
|||
[Int]add() {return $this.a + $this.b} |
|||
[Int]mul() {return $this.a * $this.b} |
|||
} |
|||
$p1 = [Point]::new() |
|||
$p2 = [Point]::new(3,2) |
|||
$p1.add() |
|||
$p2.mul() |
|||
</syntaxhighlight> |
|||
<b>Output:</b> |
|||
<pre> |
|||
0 |
|||
6 |
|||
</pre> |
|||
=={{header|Prolog}}== |
|||
Basic [http://www.purebasic.com/documentation/reference/structures.html structures]are implemented as; |
|||
Prolog terms ARE compound data types, there is no need to specifically define a type. |
|||
<lang PureBasic>Structure MyPoint |
|||
for the purpose of this exercise you could define a rule like so: |
|||
X.i |
|||
<syntaxhighlight lang="prolog">point(10, 20).</syntaxhighlight> |
|||
Y.i |
|||
This will create static point that can be called: |
|||
EndStructure</lang> |
|||
<syntaxhighlight lang="prolog">?- point(X,Y). |
|||
X = 10, |
|||
Y = 20.</syntaxhighlight> |
|||
terms can be passed around as values and can have a complex nested structure of any size, eg: |
|||
<syntaxhighlight lang="prolog">person_location(person(name(N), age(A)), point(X, Y)).</syntaxhighlight> |
|||
=={{header|PureBasic}}== |
|||
A basic [http://www.purebasic.com/documentation/reference/structures.html structure] is implemented as; |
|||
If needed StructureUnion can be used to optimize the structures |
|||
< |
<syntaxhighlight lang="purebasic">Structure MyPoint |
||
x.i |
|||
y.i |
|||
StructureUnion |
|||
EndStructure</syntaxhighlight> |
|||
Date_as_txt.s |
|||
Date_in_Ticks.l |
|||
EndStructureUnion |
|||
EndStructure</lang> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
The simplest way it to use a tuple, or a list if it should be mutable: |
The simplest way it to use a tuple, or a list if it should be mutable: |
||
< |
<syntaxhighlight lang="python">X, Y = 0, 1 |
||
p = (3, 4) |
p = (3, 4) |
||
p = [3, 4] |
p = [3, 4] |
||
print p[X]</ |
print p[X]</syntaxhighlight> |
||
If needed, you can use class: |
If needed, you can use class: |
||
< |
<syntaxhighlight lang="python">class Point: |
||
def __init__(self, x=0, y=0): |
def __init__(self, x=0, y=0): |
||
self.x = x |
self.x = x |
||
Line 1,149: | Line 2,049: | ||
p = Point() |
p = Point() |
||
print p.x</ |
print p.x</syntaxhighlight> |
||
One could also simply instantiate a generic object and "monkeypatch" it: |
One could also simply instantiate a generic object and "monkeypatch" it: |
||
< |
<syntaxhighlight lang="python">class MyObject(object): pass |
||
point = MyObject() |
point = MyObject() |
||
point.x, point.y = 0, 1 |
point.x, point.y = 0, 1 |
||
# objects directly instantiated from "object()" cannot be "monkey patched" |
# objects directly instantiated from "object()" cannot be "monkey patched" |
||
# however this can generally be done to it's subclasses</ |
# however this can generally be done to it's subclasses</syntaxhighlight> |
||
=== Dictionary === |
=== Dictionary === |
||
Mutable. Can add keys (attributes) |
Mutable. Can add keys (attributes) |
||
< |
<syntaxhighlight lang="python">pseudo_object = {'x': 1, 'y': 2}</syntaxhighlight> |
||
Line 1,168: | Line 2,068: | ||
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. |
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. |
||
< |
<syntaxhighlight lang="python">>>> from collections import namedtuple |
||
>>> help(namedtuple) |
>>> help(namedtuple) |
||
Help on function namedtuple in module collections: |
Help on function namedtuple in module collections: |
||
Line 1,194: | Line 2,094: | ||
Point(x=100, y=22) |
Point(x=100, y=22) |
||
>>></ |
>>></syntaxhighlight> |
||
=={{header|QB64}}== |
|||
<syntaxhighlight lang="qb64">Type Point |
|||
x As Double |
|||
y As Double |
|||
End Type |
|||
Dim p As Point |
|||
p.x = 15.42 |
|||
p.y = 2.412 |
|||
Print p.x; p.y</syntaxhighlight> |
|||
{{out}} |
|||
<pre> 15.42 2.412</pre> |
|||
=={{header|Quackery}}== |
|||
The single ubiquitous compound data type in Quackery is the ''nest'' (a ''mostly'' immutable dynamic array), a sequence of items wrapped in square brackets. (''Mostly'' immutable; i.e. immutable except under limited circumstances beyond the scope of this discussion. When we refer to changing the contents of a nest here, this is casual speech; a shorthand for saying "creating a new instance of the nest, identical the previous instance except where it differs".) |
|||
Presented here are two solutions to the task, the "quick and dirty" solution; sufficient to the task described here, and the "overkill" solution; extending the Quackery compiler to facilitate complex compound data structures akin to structs in C etc. |
|||
===Quick and Dirty=== |
|||
The word <code>point</code> creates an instance of a nest with two elements, both initialised to zero. The word <code>x</code> specifies the location of the zeroth element within the nest, and the word <code>y</code> specifies the location of the first element within the nest. <code>peek</code> returns the value stored in a specified location, and <code>poke</code> changes the value stored in a specified location, returning the modified nest. |
|||
<syntaxhighlight lang="quackery"> |
|||
[ ' [ 0 0 ] ] is point ( --> [ ) |
|||
[ 0 ] is x ( --> n ) |
|||
[ 1 ] is y ( --> n ) |
|||
point |
|||
dup x peek echo cr |
|||
99 swap y poke |
|||
y peek echo cr</syntaxhighlight> |
|||
{{out}} |
|||
<pre>0 |
|||
99</pre> |
|||
===Overkill=== |
|||
The "overkill" solution automates the process of creating new structures with the word <code>struct{</code>, which extends the Quackery compiler to allow the definition of complex compound data structures as follows. |
|||
<syntaxhighlight lang="quackery"> struct{ |
|||
item.0 |
|||
{ item.1.0 |
|||
item.1.1 |
|||
{ item.1.2.0 |
|||
item.1.2.1 |
|||
item.1.2.2 |
|||
item.1.2.3 |
|||
} item.1.2 |
|||
item.1.3 |
|||
} item.1 |
|||
item.2 |
|||
}struct mystruct</syntaxhighlight> |
|||
Once defined, the word <code>mystruct</code> will place a new instance of the described structure, with each item initialised to <code>null</code>, on the stack. (The behaviour of <code>null</code> is to place a reference to itself on the stack, as a convenience for debugging, and to allow code to identify elements within the structure that have not had a value assigned to them.) |
|||
The various names defined within the struct (e.g. <code>item.1.2.1</code>) return a ''path'' - a means of locating a specific item within the struct, for use by <code>{peek}</code> and <code>{poke}</code>, which have the same behaviours as <code>peek</code> and <code>poke</code>, except the they take a path to an item within a struct as an argument, rather than a number specifying an item within a nest. |
|||
Names following a <code>}</code> within the definition of a struct (e.g. <code>} item.1.2</code>) return a path to the compound data structure preceding it within the structure. In the example, <code>item.1.2</code> returns the path to <code>{ item.1.2.0 item.1.2.1 item.1.2.2 item.1.2.3 }</code> |
|||
<syntaxhighlight lang="quackery"> mystruct ( create new instance of a mystruct ) |
|||
dup echo cr ( this is what it looks like ) |
|||
789 swap item.1.3 {poke} ( change one of the items ) |
|||
dup echo cr ( this is what it looks like now ) |
|||
item.1.3 {peek} echo cr ( retrieve the specified item ) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>[ null [ null null [ null null null null ] null ] null ] |
|||
[ null [ null null [ null null null null ] 789 ] null ] |
|||
789</pre> |
|||
The words <code>{peek}</code>, <code>{poke}</code>, <code>null</code>, and the building word (i.e. compiler extension) <code>struct{</code> defined: |
|||
<syntaxhighlight lang="text"> [ witheach peek ] is {peek} ( { p --> x ) |
|||
[ dip dup |
|||
witheach [ peek dup ] |
|||
drop ] is depack ( { p --> * ) |
|||
[ reverse |
|||
witheach |
|||
[ dip swap poke ] ] is repack ( * p --> { ) |
|||
[ dup dip |
|||
[ rot dip |
|||
[ depack drop ] ] |
|||
repack ] is {poke} ( x { p --> { ) |
|||
[ this ] is null ( --> [ ) |
|||
[ stack ] is {}.path ( --> s ) |
|||
protect {}.path |
|||
[ stack ] is {}.struct ( --> s ) |
|||
protect {}.struct |
|||
[ nextword dup |
|||
$ "" = if |
|||
[ $ "Unexpected end of struct." |
|||
message put |
|||
bail ] ] is {}.checknext ( [ $ --> [ $ $ ) |
|||
[ dup $ "{" = |
|||
over $ "}" = or |
|||
swap $ "}struct" = or if |
|||
[ $ "Name missing after }." |
|||
message put |
|||
bail ] ] is {}.checkname ( [ $ $ --> [ $ ) |
|||
[ nested |
|||
namenest take |
|||
join |
|||
namenest put |
|||
' [ ' ] |
|||
{}.path share nested join |
|||
actiontable take |
|||
1 stuff |
|||
actiontable put ] is {}.addpath ( [ $ $ --> [ $ ) |
|||
[ nested |
|||
namenest take |
|||
join |
|||
namenest put |
|||
' [ ' ] |
|||
{}.struct share nested join |
|||
actiontable take |
|||
1 stuff |
|||
actiontable put ] is {}.addstruct ( [ $ $ --> [ $ ) |
|||
[ {}.path take |
|||
dup -1 peek |
|||
1+ |
|||
swap -1 poke |
|||
-1 join |
|||
{}.path put |
|||
[] {}.struct put ] is {}.{ ( [ $ --> [ $ ) |
|||
[ {}.struct size 3 < if |
|||
[ $ "Badly formed struct." |
|||
message put bail ] |
|||
trim {}.checknext |
|||
dup {}.checkname |
|||
{}.path take |
|||
-1 split drop |
|||
{}.path put |
|||
{}.addpath |
|||
{}.struct take |
|||
{}.struct take |
|||
swap nested join |
|||
{}.struct put ] is {}.} ( [ $ --> [ $ ) |
|||
[ {}.path take |
|||
dup -1 peek |
|||
1+ |
|||
swap -1 poke |
|||
{}.path put |
|||
{}.addpath |
|||
{}.struct take |
|||
' [ null ] join |
|||
{}.struct put ] is {}.name ( [ $ --> [ $ ) |
|||
[ trim {}.checknext |
|||
{}.struct size |
|||
2 != if |
|||
[ $ "Badly formed struct." |
|||
message put |
|||
bail ] |
|||
{}.addstruct ] is {}.}struct ( [ $ --> [ $ ) |
|||
[ ' [ -1 ] {}.path put |
|||
[] {}.struct put |
|||
[ trim {}.checknext |
|||
dup $ "{" = iff |
|||
[ drop {}.{ ] again |
|||
dup $ "}" = iff |
|||
[ drop {}.} ] again |
|||
dup $ "}struct" = iff |
|||
[ drop {}.}struct ] done |
|||
{}.name again ] |
|||
{}.struct release |
|||
{}.path release ] builds struct{ ( [ $ --> [ $ )</syntaxhighlight> |
|||
Finally we use <code>struct{</code> etc. to fulfil the requirements go the task. |
|||
<syntaxhighlight lang="quackery"> struct{ x y }struct point |
|||
point |
|||
dup x {peek} echo cr |
|||
99 swap y {poke} |
|||
y {peek} echo cr</syntaxhighlight> |
|||
{{out}} |
|||
<pre>null |
|||
99 |
|||
</pre> |
|||
=={{header|R}}== |
=={{header|R}}== |
||
R uses the list data type for compound data. |
R uses the list data type for compound data. |
||
< |
<syntaxhighlight lang="r">mypoint <- list(x=3.4, y=6.7) |
||
# $x |
# $x |
||
# [1] 3.4 |
# [1] 3.4 |
||
Line 1,217: | Line 2,320: | ||
# [1] 1 |
# [1] 1 |
||
# $d$f |
# $d$f |
||
# [1] TRUE</ |
# [1] TRUE</syntaxhighlight> |
||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
Line 1,223: | Line 2,326: | ||
The most common method uses structures (similar to records): |
The most common method uses structures (similar to records): |
||
< |
<syntaxhighlight lang="racket"> |
||
#lang racket |
#lang racket |
||
(struct point (x y)) |
(struct point (x y)) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Alternatively, you can define a class: |
Alternatively, you can define a class: |
||
< |
<syntaxhighlight lang="racket"> |
||
#lang racket |
#lang racket |
||
(define point% ; classes are suffixed with % by convention |
(define point% ; classes are suffixed with % by convention |
||
Line 1,236: | Line 2,339: | ||
(super-new) |
(super-new) |
||
(init-field x y))) |
(init-field x y))) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
{{works with|Rakudo|#24 "Seoul"}} |
|||
===Array=== |
|||
<syntaxhighlight lang="raku" line>my @point = 3, 8; |
|||
my Int @point = 3, 8; # or constrain to integer elements</syntaxhighlight> |
|||
===Hash=== |
|||
<syntaxhighlight lang="raku" line>my %point = x => 3, y => 8; |
|||
my Int %point = x => 3, y => 8; # or constrain the hash to have integer values</syntaxhighlight> |
|||
===Class instance=== |
|||
<syntaxhighlight lang="raku" line>class Point { has Real ($.x, $.y) is rw; } |
|||
my Point $point .= new: x => 3, y => 8;</syntaxhighlight> |
|||
===[http://design.raku.org/S32/Containers.html#Set Set]=== |
|||
<syntaxhighlight lang="raku" line>my $s1 = set <a b c d>; # order is not preserved |
|||
my $s2 = set <c d e f>; |
|||
say $s1 (&) $s2; # OUTPUT«set(c, e)» |
|||
say $s1 ∩ $s2; # we also do Unicode</syntaxhighlight> |
|||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
<syntaxhighlight lang="rexx">x= -4.9 |
|||
<lang rexx> |
|||
x= -4.9 |
|||
y= 1.7 |
y= 1.7 |
||
point=x y |
point=x y</syntaxhighlight> |
||
:: ---or--- |
|||
</lang> |
|||
<syntaxhighlight lang="rexx">x= -4.1 |
|||
---or--- |
|||
<lang rexx> |
|||
x= -4.1 |
|||
y= 1/4e21 |
y= 1/4e21 |
||
Line 1,254: | Line 2,378: | ||
bpoint=point |
bpoint=point |
||
gpoint=5.6 7.3e-12 |
gpoint=5.6 7.3e-12</syntaxhighlight> |
||
</lang> |
|||
=={{header|Ring}}== |
|||
<syntaxhighlight lang="ring"> |
|||
see new point {x=10 y=20} class point x y |
|||
</syntaxhighlight> |
|||
Output |
|||
<syntaxhighlight lang="ring"> |
|||
x: 10.000000 |
|||
y: 20.000000 |
|||
</syntaxhighlight> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
< |
<syntaxhighlight lang="ruby">Point = Struct.new(:x,:y) |
||
pt = Point.new(6,7) |
pt = Point.new(6,7) |
||
puts pt.x #=> 6 |
puts pt.x #=> 6 |
||
Line 1,272: | Line 2,405: | ||
pt.each_pair{|member, value| puts "#{member} : #{value}"} |
pt.each_pair{|member, value| puts "#{member} : #{value}"} |
||
#=> x : 2 |
#=> x : 2 |
||
#=> y : 5</ |
#=> y : 5</syntaxhighlight> |
||
=={{header|Rust}}== |
|||
===Structs=== |
|||
There are three kinds of <code>struct</code>s in Rust, two of which would be suitable to represent a point. |
|||
====C-like struct==== |
|||
<syntaxhighlight lang="rust"> // Defines a generic struct where x and y can be of any type T |
|||
struct Point<T> { |
|||
x: T, |
|||
y: T, |
|||
} |
|||
fn main() { |
|||
let p = Point { x: 1.0, y: 2.5 }; // p is of type Point<f64> |
|||
println!("{}, {}", p.x, p.y); |
|||
} </syntaxhighlight> |
|||
====Tuple struct==== |
|||
These are basically just named tuples. |
|||
<syntaxhighlight lang="rust">struct Point<T>(T, T); |
|||
fn main() { |
|||
let p = Point(1.0, 2.5); |
|||
println!("{},{}", p.0, p.1); |
|||
}</syntaxhighlight> |
|||
===Tuples=== |
|||
<syntaxhighlight lang="rust"> fn main() { |
|||
let p = (0.0, 2.4); |
|||
println!("{},{}", p.0, p.1); |
|||
}</syntaxhighlight> |
|||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
< |
<syntaxhighlight lang="scala">case class Point(x: Int = 0, y: Int = 0) |
||
val p=Point(1,2) |
val p = Point(1, 2) |
||
println(p.y) //=> 2</ |
println(p.y) //=> 2</syntaxhighlight> |
||
=={{header|Scheme}}== |
=={{header|Scheme}}== |
||
Using [http://srfi.schemers.org/srfi-9/srfi-9.html SRFI 9]: |
Using [http://srfi.schemers.org/srfi-9/srfi-9.html SRFI 9]: |
||
< |
<syntaxhighlight lang="scheme">(define-record-type point |
||
(make-point x y) |
(make-point x y) |
||
point? |
point? |
||
(x point-x) |
(x point-x) |
||
(y point-y))</ |
(y point-y))</syntaxhighlight> |
||
=={{header|Seed7}}== |
=={{header|Seed7}}== |
||
< |
<syntaxhighlight lang="seed7">const type: Point is new struct |
||
var integer: x is 0; |
var integer: x is 0; |
||
var integer: y is 0; |
var integer: y is 0; |
||
end struct;</ |
end struct;</syntaxhighlight> |
||
=={{header|Shen}}== |
|||
<syntaxhighlight lang="shen">(datatype point |
|||
X : number; Y : number; |
|||
==================== |
|||
[point X Y] : point;)</syntaxhighlight> |
|||
Pairs (distinct from cons cells) are also supported, in which case a point would be denoted by (number * number): |
|||
<syntaxhighlight lang="shen">(2+) (@p 1 2) |
|||
(@p 1 2) : (number * number)</syntaxhighlight> |
|||
=={{header|Sidef}}== |
|||
<syntaxhighlight lang="ruby">struct Point {x, y}; |
|||
var point = Point(1, 2); |
|||
say point.y; #=> 2</syntaxhighlight> |
|||
=={{header|SIMPOL}}== |
=={{header|SIMPOL}}== |
||
The <code>point</code> type is pre-defined in [SIMPOL], so we will call this mypoint. |
The <code>point</code> type is pre-defined in [SIMPOL], so we will call this mypoint. |
||
< |
<syntaxhighlight lang="simpol">type mypoint |
||
embed |
embed |
||
integer x |
integer x |
||
integer y |
integer y |
||
end type</ |
end type</syntaxhighlight> |
||
The <code>embed</code> keyword is used here as a toggle to indicate that all following properties are embedded in the type. The other toggle is <code>reference</code>, 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. |
The <code>embed</code> keyword is used here as a toggle to indicate that all following properties are embedded in the type. The other toggle is <code>reference</code>, 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. |
||
Line 1,307: | Line 2,482: | ||
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. |
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. |
||
< |
<syntaxhighlight lang="simpol">type mypoint |
||
embed |
embed |
||
integer x |
integer x |
||
Line 1,316: | Line 2,491: | ||
me.x = x |
me.x = x |
||
me.y = y |
me.y = y |
||
end function me</ |
end function me</syntaxhighlight> |
||
=={{header|SNOBOL4}}== |
=={{header|SNOBOL4}}== |
||
< |
<syntaxhighlight lang="snobol"> data('point(x,y)') |
||
p1 = point(10,20) |
p1 = point(10,20) |
||
p2 = point(10,40) |
p2 = point(10,40) |
||
output = "Point 1 (" x(p1) "," y(p1) ")" |
output = "Point 1 (" x(p1) "," y(p1) ")" |
||
output = "Point 2 (" x(p2) "," y(p2) ")" |
output = "Point 2 (" x(p2) "," y(p2) ")" |
||
end</ |
end</syntaxhighlight> |
||
=={{header|Standard ML}}== |
=={{header|Standard ML}}== |
||
Line 1,332: | Line 2,507: | ||
See [[wp:Algebraic_data_type|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. |
See [[wp:Algebraic_data_type|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. |
||
< |
<syntaxhighlight lang="sml">datatype tree = Empty |
||
| Leaf of int |
| Leaf of int |
||
| Node of tree * tree |
| Node of tree * tree |
||
val t1 = Node (Leaf 1, Node (Leaf 2, Leaf 3))</ |
val t1 = Node (Leaf 1, Node (Leaf 2, Leaf 3))</syntaxhighlight> |
||
===Tuple Type=== |
===Tuple Type=== |
||
Line 1,342: | Line 2,517: | ||
You can make a tuple literal by using a comma-delimited list surrounded by parentheses, without needing to declare the type first: |
You can make a tuple literal by using a comma-delimited list surrounded by parentheses, without needing to declare the type first: |
||
< |
<syntaxhighlight lang="sml">val p = (2,3)</syntaxhighlight> |
||
The type of <code>p</code> is a product (indicated by <code>*</code>) of the types of the components: |
The type of <code>p</code> is a product (indicated by <code>*</code>) of the types of the components: |
||
Line 1,359: | Line 2,534: | ||
You can make a record literal by using a comma-delimited list of <code>key = value</code> pairs surrounded by curly braces, without needing to declare the type first: |
You can make a record literal by using a comma-delimited list of <code>key = value</code> pairs surrounded by curly braces, without needing to declare the type first: |
||
< |
<syntaxhighlight lang="sml">val p = { x = 4, y = 5 }</syntaxhighlight> |
||
The type of <code>p</code> is a comma-delimited list of <code>key:type</code> pairs of the types of the fields: |
The type of <code>p</code> is a comma-delimited list of <code>key:type</code> pairs of the types of the fields: |
||
Line 1,369: | Line 2,544: | ||
val it = 5 : int |
val it = 5 : int |
||
The <code>#y</code> above extracts the field named "y" of its argument. |
The <code>#y</code> above extracts the field named "y" of its argument. |
||
=={{header|Stata}}== |
|||
See '''[https://www.stata.com/help.cgi?m2_struct struct]''' in Stata help. |
|||
<syntaxhighlight lang="stata">mata |
|||
struct Point { |
|||
real scalar x, y |
|||
} |
|||
// dumb example |
|||
function test() { |
|||
struct Point scalar a |
|||
a.x = 10 |
|||
a.y = 20 |
|||
printf("%f\n",a.x+a.y) |
|||
} |
|||
test() |
|||
30 |
|||
end</syntaxhighlight> |
|||
=={{header|Swift}}== |
|||
<syntaxhighlight lang="swift">// Structure |
|||
struct Point { |
|||
var x:Int |
|||
var y:Int |
|||
} |
|||
// Tuple |
|||
typealias PointTuple = (Int, Int) |
|||
// Class |
|||
class PointClass { |
|||
var x:Int! |
|||
var y:Int! |
|||
init(x:Int, y:Int) { |
|||
self.x = x |
|||
self.y = y |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
This can be done using an associative array: |
This can be done using an associative array: |
||
< |
<syntaxhighlight lang="tcl">array set point {x 4 y 5} |
||
set point(y) 7 |
set point(y) 7 |
||
puts "Point is {$point(x),$point(y)}" |
puts "Point is {$point(x),$point(y)}" |
||
# => Point is {4,7}</ |
# => Point is {4,7}</syntaxhighlight> |
||
Or a dictionary: |
Or a dictionary: |
||
{{works with|Tcl|8.5}} |
{{works with|Tcl|8.5}} |
||
< |
<syntaxhighlight lang="tcl">set point [dict create x 4 y 5] |
||
dict set point y 7 |
dict set point y 7 |
||
puts "Point is {[dict get $point x],[dict get $point y]}"</ |
puts "Point is {[dict get $point x],[dict get $point y]}"</syntaxhighlight> |
||
Or an object: |
Or an object: |
||
{{works with|Tcl|8.6}} |
{{works with|Tcl|8.6}} |
||
< |
<syntaxhighlight lang="tcl">oo::class create Point { |
||
variable x y |
variable x y |
||
constructor {X Y} {set x $X;set y $Y} |
constructor {X Y} {set x $X;set y $Y} |
||
Line 1,392: | Line 2,608: | ||
Point create point 4 5 |
Point create point 4 5 |
||
point y 7 |
point y 7 |
||
puts "Point is [point show]"</ |
puts "Point is [point show]"</syntaxhighlight> |
||
=={{header|TI-89 BASIC}}== |
=={{header|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. |
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. |
||
=={{header|Transd}}== |
|||
<syntaxhighlight lang="Scheme">#lang transd |
|||
// If the Point type needs encapsulation and/or methods, it should be |
|||
// implemented as class. Otherwise, the named tuple will do. |
|||
class Point: { |
|||
x: Double(), y: Double(), |
|||
@init: (λ _x Double() _y Double() (= x _x) (= y _y)), |
|||
@to-String: (λ ss StringStream() (textout to: ss |
|||
"Point( x: " x "; y: " y " )")) |
|||
// ... other methods can be defined here ... |
|||
} |
|||
MainModule: { |
|||
Point2: typealias(Tuple<Double Double>()), |
|||
_start: (λ |
|||
(with pt Point(2.5 3.7) |
|||
(lout "Class: " pt) |
|||
) |
|||
(with pt Point2(2.5 3.7) |
|||
(lout "\nNamed tuple: " pt) |
|||
) |
|||
) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Class: Point( x: 2.5; y: 3.7 ) |
|||
Named tuple: [[2.5, 3.7]] |
|||
</pre> |
|||
=={{header|TXR}}== |
|||
In TXR Lisp, a structure type can be created: |
|||
<syntaxhighlight lang="txrlisp">(defstruct point nil (x 0) (y 0))</syntaxhighlight> |
|||
If it is okay for the coordinates to be initialized to <tt>nil</tt>, it can be condensed to: |
|||
<syntaxhighlight lang="txrlisp">(defstruct point nil x y)</syntaxhighlight> |
|||
The <tt>nil</tt> denotes that a <tt>point</tt> has no supertype: it doesn't inherit from anything. |
|||
This structure type can then be instantiated using the <tt>new</tt> macro (not the only way): |
|||
<syntaxhighlight lang="txrlisp">(new point) ;; -> #S(point x 0 y 0) |
|||
(new point x 1) ;; -> #S(point x 1 y 0) |
|||
(new point x 1 y 1) ;; -> #S(point x 1 y 1)</syntaxhighlight> |
|||
A structure can support optional by-order-of-arguments ("boa") construction by providing a "boa constructor". The <tt>defstruct</tt> syntactic sugar does this if a function-like syntax is used in place of the structure name: |
|||
<syntaxhighlight lang="txrlisp">(defstruct (point x y) nil (x 0) (y 0))</syntaxhighlight> |
|||
The existing construction methods continue to work, but in addition, this is now possible: |
|||
<syntaxhighlight lang="txrlisp">(new (point 3 4)) -> #S(point x 3 y 4)</syntaxhighlight> |
|||
Slot access syntax is supported. If variable <tt>p</tt> holds a point, then <tt>p.x</tt> designates the <tt>x</tt> slot, as a syntactic place which can be accessed and stored: |
|||
<syntaxhighlight lang="txrlisp">(defun displace-point-destructively (p delta) |
|||
(inc p.x delta.x) |
|||
(inc p.y delta.y))</syntaxhighlight> |
|||
=={{header|UNIX Shell}}== |
|||
{{works with|ksh93}} |
|||
ksh93 allows you to define new compound types with the <tt>typeset -T</tt> command. |
|||
<syntaxhighlight lang="bash">typeset -T Point=( |
|||
typeset x |
|||
typeset y |
|||
) |
|||
Point p |
|||
p.x=1 |
|||
p.y=2 |
|||
echo $p |
|||
echo ${p.x} ${p.y} |
|||
Point q=(x=3 y=4) |
|||
echo ${q.x} ${q.y}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>( x=1 y=2 ) |
|||
1 2 |
|||
3 4</pre> |
|||
You can also declare compound variables "on the fly" without using a defined type: |
|||
<syntaxhighlight lang="bash">point=() |
|||
point.x=5 |
|||
point.y=6 |
|||
echo $point |
|||
echo ${point.x} ${point.y}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>( x=5 y=6 ) |
|||
5 6</pre> |
|||
=={{header|Ursala}}== |
=={{header|Ursala}}== |
||
A record type with two untyped fields named <code>x</code> and <code>y</code> can be declared like this. |
A record type with two untyped fields named <code>x</code> and <code>y</code> can be declared like this. |
||
<lang |
<syntaxhighlight lang="ursala">point :: x y</syntaxhighlight> |
||
A constant instance of the record can be declared like this. |
A constant instance of the record can be declared like this. |
||
< |
<syntaxhighlight lang="ursala">p = point[x: 'foo',y: 'bar']</syntaxhighlight> |
||
A function returning a value of this type can be defined like this, |
A function returning a value of this type can be defined like this, |
||
< |
<syntaxhighlight lang="ursala">f = point$[x: g,y: h]</syntaxhighlight> |
||
where <code>g</code> and <code>h</code> are functions. Then <code>f(p)</code> would evaluate to |
where <code>g</code> and <code>h</code> are functions. Then <code>f(p)</code> would evaluate to |
||
<code>point[x: g(p),y: h(p)]</code> for a given argument <code>p</code>. Accessing the fields of |
<code>point[x: g(p),y: h(p)]</code> for a given argument <code>p</code>. Accessing the fields of |
||
a record can be done like this. |
a record can be done like this. |
||
< |
<syntaxhighlight lang="ursala">t = ~x p |
||
u = ~y p</ |
u = ~y p</syntaxhighlight> |
||
where <code>p</code> is any expression of the defined type. A real application wouldn't be written |
where <code>p</code> is any expression of the defined type. A real application wouldn't be written |
||
this way because pairs of values <code>(x,y)</code> are a common idiom. |
this way because pairs of values <code>(x,y)</code> are a common idiom. |
||
=={{header| |
=={{header|Vala}}== |
||
<syntaxhighlight lang="vala">struct Point { |
|||
int x; |
|||
int y; |
|||
}</syntaxhighlight> |
|||
=={{header|VBA}}== |
|||
=== Simple Structures === |
|||
<syntaxhighlight lang="vb">Type point |
|||
x As Integer |
|||
y As Integer |
|||
End Type</syntaxhighlight> |
|||
=={{header|Vim Script}}== |
|||
This shows a structure in its simpest form. |
|||
One cannot create new data types in Vim Script. A point could be represented by a dictionary: |
|||
<syntaxhighlight lang="vim">function MakePoint(x, y) " 'Constructor' |
|||
<lang vbnet>Structure Simple_Point |
|||
return {"x": a:x, "y": a:y} |
|||
endfunction |
|||
let p1 = MakePoint(3, 2) |
|||
let p2 = MakePoint(-1, -4) |
|||
echon "Point 1: x = " p1.x ", y = " p1.y "\n" |
|||
echon "Point 2: x = " p2.x ", y = " p2.y "\n"</syntaxhighlight> |
|||
{{Out}} |
|||
<pre>Point 1: x = 3, y = 2 |
|||
Point 2: x = -1, y = -4</pre> |
|||
=={{header|Visual Basic .NET}}== |
|||
=== Structures === |
|||
A simple structure with two public, mutable fields: |
|||
<syntaxhighlight lang="vbnet">Structure Point |
|||
Public X, Y As Integer |
Public X, Y As Integer |
||
End Structure</ |
End Structure</syntaxhighlight> |
||
=== Immutable Structures === |
=== Immutable Structures === |
||
It is generally recommended in .NET that mutable structures only be used in niche cases where they provide needed performance, e.g. when the creation of massive numbers of class instances would cause excessive garbage collection pressure, as high-performance code dealing with structs generally is of a paradigm considered "impure" from an object-oriented perspective that relies on passing by reference and directly exposing fields. |
|||
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. |
|||
The semantics of value types in .NET mean that a new copy of a structure is created whenever one is passed by value to or from a method or property. This is particularly vexing when properties are involved, as it is not possible to mutate a structure that is returned by a property, due to the returned structure actually being an independent copy of whatever the property originally returned. The only workaround would be to store the value of the property in a temporary variable, mutate that variable, and assign the mutated variable back to the property, which involves another copy operation. When a structure is large, this copying can significantly affect performance. |
|||
<lang vbnet>Structure Immutable_Point |
|||
Private m_X As Integer |
|||
Private m_Y As Integer |
|||
On another note, algorithms relying on immutable data structures are often more easily parallelized, as they eliminate the race conditions caused by concurrent reading and writing. |
|||
Public Sub New(ByVal x As Integer, ByVal y As Integer) |
|||
m_X = x |
|||
Below is the same <code>Point</code> as above, except with an immutable API. |
|||
m_Y = y |
|||
<syntaxhighlight lang="vbnet">Structure ImmutablePoint |
|||
ReadOnly Property X As Integer |
|||
ReadOnly Property Y As Integer |
|||
Public Sub New(x As Integer, y As Integer) |
|||
Me.X = x |
|||
Me.Y = y |
|||
End Sub |
End Sub |
||
End Structure</syntaxhighlight> |
|||
=={{header|V (Vlang)}}== |
|||
Public ReadOnly Property X() As Integer |
|||
Vlang also supports embedding structs into other structs and assigning methods to structs. |
|||
Get |
|||
<syntaxhighlight lang="v (vlang)">struct Point { |
|||
Return m_X |
|||
x int |
|||
y int |
|||
} |
|||
// main() declaration can be skipped in one file programs |
|||
Public ReadOnly Property Y() As Integer |
|||
// we can define whether immutable or mutable by using the "mut" keyword |
|||
Get |
|||
Return m_Y |
|||
End Get |
|||
End Property |
|||
mut p := Point{ |
|||
End Structure</lang> |
|||
x: 10 |
|||
y: 20 |
|||
} |
|||
// struct fields are accessed using a dot |
|||
println("Value of p.x is: $p.x") |
|||
println("Show the struct:\n $p") |
|||
// alternative literal syntax can be used for structs with 3 fields or fewer |
|||
p = Point{30, 40} |
|||
assert p.x == 30 |
|||
println("Show the struct again after change:\n $p") |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Value of p.x is: 10 |
|||
Show the struct: |
|||
Point{ |
|||
x: 10 |
|||
y: 20 |
|||
} |
|||
Show the struct again after change: |
|||
Point{ |
|||
x: 30 |
|||
y: 40 |
|||
} |
|||
</pre> |
|||
=={{header|Wren}}== |
|||
<syntaxhighlight lang="wren">class Point { |
|||
construct new(x, y) { |
|||
_x = x |
|||
_y = y |
|||
} |
|||
x { _x } |
|||
y { _y } |
|||
// for illustration allow Points to be mutated |
|||
x=(value) { _x = value } |
|||
y=(value) { _y = value } |
|||
toString { "(%(_x), %(_y))" } |
|||
} |
|||
var p = Point.new(1, 2) |
|||
System.print(p.toString) |
|||
// mutate Point object |
|||
p.x = 2 |
|||
p.y = 3 |
|||
// print without using the toString method |
|||
System.printAll(["(", p.x, ", ", p.y, ")"])</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
(1, 2) |
|||
(2, 3) |
|||
</pre> |
|||
=={{header|XSLT}}== |
=={{header|XSLT}}== |
||
Line 1,456: | Line 2,857: | ||
===Attributes=== |
===Attributes=== |
||
Attributes are often used for simple values. This is how a point might be represented in SVG, for example. |
Attributes are often used for simple values. This is how a point might be represented in SVG, for example. |
||
< |
<syntaxhighlight lang="xml"><point x="20" y="30"/> |
||
<!-- context is a point node. The '@' prefix selects named attributes of the current node. --> |
<!-- 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></ |
<fo:block>Point = <xsl:value-of select="@x"/>, <xsl:value-of select="@y"/></fo:block></syntaxhighlight> |
||
===Children=== |
===Children=== |
||
More complex, multivariate, and nested data structures can be represented using child nodes. |
More complex, multivariate, and nested data structures can be represented using child nodes. |
||
< |
<syntaxhighlight lang="xml"><circle> |
||
<point> |
<point> |
||
<x>20</x> |
<x>20</x> |
||
Line 1,471: | Line 2,872: | ||
</circle> |
</circle> |
||
<!-- context is a circle node. Children are accessed using a path-like notation (hence the name "XPath"). --></ |
<!-- context is a circle node. Children are accessed using a path-like notation (hence the name "XPath"). --></syntaxhighlight> |
||
<fo:block>Circle center = <xsl:value-of select="point/x"/>, <xsl:value-of select="point/y"/></fo:block> |
<fo:block>Circle center = <xsl:value-of select="point/x"/>, <xsl:value-of select="point/y"/></fo:block> |
||
=={{header|Z80 Assembly}}== |
|||
We'll declare the following C struct: |
|||
<syntaxhighlight lang="c">struct Point{ |
|||
char x; |
|||
char y; |
|||
}</syntaxhighlight> |
|||
and then execute the following C code as Z80 Assembly below. |
|||
<syntaxhighlight lang="c">struct Point myPoint; |
|||
myPoint.x = 3; |
|||
myPoint.y = 5;</syntaxhighlight> |
|||
<syntaxhighlight lang="z80">;I'm arbitrarily choosing &1100 as the memory location of our Point variable. |
|||
ld hl,&1100 |
|||
ld (hl),3 |
|||
inc hl |
|||
ld (hl),5 |
|||
ret</syntaxhighlight> |
|||
=={{header|zkl}}== |
|||
The OO solution: |
|||
<syntaxhighlight lang="zkl">class Point{ var x,y; |
|||
fcn init(x,y){self.x=x.toFloat(); self.y=y.toFloat(); } |
|||
fcn toString{ "P(%f,%f)".fmt(x,y) } |
|||
fcn __opADD(P){} //+: add Point, constant or whatever |
|||
//... __opEQ == etc |
|||
} |
|||
Point(1,2).println() //-->P(1.000000,2.000000)</syntaxhighlight> |
|||
which can be pretty heavy weight. [read only] lists can work just as well: |
|||
<syntaxhighlight lang="zkl">point:=T(1,2); points:=T( T(1,2), L(3,4) )</syntaxhighlight> |
|||
{{omit from|bc}} |
|||
{{omit from|dc}} |
|||
=={{header|zonnon}}== |
|||
<syntaxhighlight lang="zonnon"> |
|||
{ref,public} (* class *) |
|||
Point = object(ord,abs: integer) |
|||
var |
|||
(* instance variables *) |
|||
{public,immutable} x,y: integer; |
|||
(* method *) |
|||
procedure {public} Ord():integer; |
|||
begin |
|||
return y |
|||
end Ord; |
|||
(* method *) |
|||
procedure {public} Abs():integer; |
|||
begin |
|||
return x |
|||
end Abs; |
|||
(* constructor *) |
|||
begin |
|||
self.x := ord; |
|||
self.y := abs; |
|||
end Point; |
|||
</syntaxhighlight> |
Latest revision as of 07:51, 21 May 2024
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.
- Task
Create a compound data type:
Point(x,y)
A compound data type is one that holds multiple independent values.
- Related task
- See also
- Array
- Associative array: Creation, Iteration
- Collections
- Compound data type
- Doubly-linked list: Definition, Element definition, Element insertion, List Traversal, Element Removal
- Linked list
- Queue: Definition, Usage
- Set
- Singly-linked list: Element definition, Element insertion, List Traversal, Element Removal
- Stack
11l
T Point
Int x, y
F (x, y)
.x = x
.y = y
ACL2
(defstructure point
(x (:assert (rationalp x)))
(y (:assert (rationalp y))))
(assign p1 (make-point :x 1 :y 2))
(point-x (@ p1)) ; Access the x value of the point
(assign p1 (update-point (@ p1) :x 3)) ; Update the x value
(point-x (@ p1))
(point-p (@ p1)) ; Recognizer for points
- Output:
((:X . 1) (:Y . 2)) 1 ((:X . 3) (:Y . 2)) 3 T
6502 Assembly
The method below is a bit unusual compared to C, where each member of a struct is stored consecutively. The addressing modes of 6502 make it much more efficient to store each member of many different structs consecutively. In other words, the index used to offset into point_x
represents which instance of the data type the CPU is accessing. Of course, this assumes that you're willing to declare in advance how many active instances of that data type you'll ever have at once, a very frequent practice in the 8-bit assembly world but is absolutely ludicrous in high-level languages.
NESASM3 syntax:
MAX_POINT_OBJECTS = 64 ; define a constant
.rsset $0400 ; reserve memory storage starting at address $0400
point_x .rs MAX_POINT_OBJECTS ; reserve 64 bytes for x-coordinates
point_y .rs MAX_POINT_OBJECTS ; reserve 64 bytes for y-coordinates
VASM syntax:
MAX_POINT_OBJECTS equ 64
point_ram equ $0400
point_x equ point_ram
point_y equ point_ram+MAX_POINT_OBJECTS
So, for example, let's say we want to load our third (zero-indexed) point variable and copy it to zero page RAM addresses $00 and $01. We would do the following:
MAX_POINT_OBJECTS equ 64
point_ram equ $0400
point_x equ point_ram
point_y equ point_ram+MAX_POINT_OBJECTS
LDX #3
LDA point_x,x
STA $00
LDA point_y,x
STA $01
Action!
INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit
DEFINE REALPTR="CARD"
TYPE PointI=[INT x,y]
TYPE PointR=[REALPTR rx,ry]
PROC Main()
PointI p1
PointR p2
REAL realx,realy
Put(125) PutE() ;clear screen
p1.x=123
p1.y=4567
ValR("12.34",realx)
ValR("5.6789",realy)
p2.rx=realx
p2.ry=realy
PrintF("Integer point p1=(%I,%I)%E",p1.x,p1.y)
Print("Real point p2=(")
PrintR(p2.rx) Print(",")
PrintR(p2.ry) Print(")")
RETURN
- Output:
Screenshot from Atari 8-bit computer
Integer point p1=(123,4567) Real point p2=(12.34,5.6789)
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;
}
}
}
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.
type Point is tagged record
X : Integer := 0;
Y : Integer := 0;
end record;
Record Type
Ada record types are not extensible through inheritance. Without the reserved word tagged the record does not belong to an inheritance hierarchy.
type Point is record
X : Integer := 0;
Y : Integer := 0;
end record;
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.
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;
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.
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.
ALGOL W
begin
% create the compound data type %
record Point( real x, y );
% declare a Point variable %
reference(Point) p;
% assign a value to p %
p := Point( 1, 0.5 );
% access the fields of p - note Algol W uses x(p) where many languages would use p.x %
write( x(p), y(p) )
end.
AmigaE
OBJECT point
x, y
ENDOBJECT
PROC main()
DEF pt:PTR TO point,
NEW pt
-> Floats are also stored as integer types making
-> the float conversion operator necessary.
pt.x := !10.4
pt.y := !3.14
END pt
ENDPROC
ARM Assembly
/* ARM assembly Raspberry PI */
/* program structure.s */
/************************************/
/* Constantes */
/************************************/
.equ STDOUT, 1 @ Linux output console
.equ EXIT, 1 @ Linux syscall
.equ WRITE, 4 @ Linux syscall
/*******************************************/
/* Structures */
/********************************************/
.struct 0
point_x: @ x coordinate
.struct point_x + 4
point_y: @ y coordinate
.struct point_y + 4
point_end: @ end structure point
/*********************************/
/* Initialized data */
/*********************************/
.data
sMessResult: .ascii "value x : "
sMessValeur: .fill 11, 1, ' ' @ size => 11
szCarriageReturn: .asciz "\n"
/*********************************/
/* UnInitialized data */
/*********************************/
.bss
stPoint: .skip point_end @ reservation place in memory
/*********************************/
/* code section */
/*********************************/
.text
.global main
main: @ entry of program
ldr r1,iAdrstPoint
mov r0,#5 @ x value
str r0,[r1,#point_x]
mov r0,#10 @ y value
str r0,[r1,#point_y]
@ display value
ldr r2,iAdrstPoint
ldr r0,[r2,#point_x]
ldr r1,iAdrsMessValeur
bl conversion10 @ call conversion decimal
ldr r0,iAdrsMessResult
bl affichageMess @ display message
100: @ standard end of the program
mov r0, #0 @ return code
mov r7, #EXIT @ request to exit program
svc #0 @ perform the system call
iAdrsMessValeur: .int sMessValeur
iAdrszCarriageReturn: .int szCarriageReturn
iAdrsMessResult: .int sMessResult
iAdrstPoint: .int stPoint
/******************************************************************/
/* display text with size calculation */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
push {r0,r1,r2,r7,lr} @ save registres
mov r2,#0 @ counter length
1: @ loop length calculation
ldrb r1,[r0,r2] @ read octet start position + index
cmp r1,#0 @ if 0 its over
addne r2,r2,#1 @ else add 1 in the length
bne 1b @ and loop
@ so here r2 contains the length of the message
mov r1,r0 @ address message in r1
mov r0,#STDOUT @ code to write to the standard output Linux
mov r7, #WRITE @ code call system "write"
svc #0 @ call systeme
pop {r0,r1,r2,r7,lr} @ restaur des 2 registres */
bx lr @ return
/******************************************************************/
/* Converting a register to a decimal unsigned */
/******************************************************************/
/* r0 contains value and r1 address area */
/* r0 return size of result (no zero final in area) */
/* area size => 11 bytes */
.equ LGZONECAL, 10
conversion10:
push {r1-r4,lr} @ save registers
mov r3,r1
mov r2,#LGZONECAL
1: @ start loop
bl divisionpar10U @ unsigned r0 <- dividende. quotient ->r0 reste -> r1
add r1,#48 @ digit
strb r1,[r3,r2] @ store digit on area
cmp r0,#0 @ stop if quotient = 0
subne r2,#1 @ else previous position
bne 1b @ and loop
@ and move digit from left of area
mov r4,#0
2:
ldrb r1,[r3,r2]
strb r1,[r3,r4]
add r2,#1
add r4,#1
cmp r2,#LGZONECAL
ble 2b
@ and move spaces in end on area
mov r0,r4 @ result length
mov r1,#' ' @ space
3:
strb r1,[r3,r4] @ store space in area
add r4,#1 @ next position
cmp r4,#LGZONECAL
ble 3b @ loop if r4 <= area size
100:
pop {r1-r4,lr} @ restaur registres
bx lr @return
/***************************************************/
/* division par 10 unsigned */
/***************************************************/
/* r0 dividende */
/* r0 quotient */
/* r1 remainder */
divisionpar10U:
push {r2,r3,r4, lr}
mov r4,r0 @ save value
ldr r3,iMagicNumber @ r3 <- magic_number raspberry 1 2
umull r1, r2, r3, r0 @ r1<- Lower32Bits(r1*r0) r2<- Upper32Bits(r1*r0)
mov r0, r2, LSR #3 @ r2 <- r2 >> shift 3
add r2,r0,r0, lsl #2 @ r2 <- r0 * 5
sub r1,r4,r2, lsl #1 @ r1 <- r4 - (r2 * 2) = r4 - (r0 * 10)
pop {r2,r3,r4,lr}
bx lr @ leave function
iMagicNumber: .int 0xCCCCCCCD
Arturo
point: #[
x: 10
y: 20
]
print point
- Output:
[x:10 y:20]
ATS
There are numerous ways to do this. The simplest is to use an "unboxed" tuple type:
typedef point (t : t@ype+) = @(t, t)
val p : point double = (1.0, 3.0)
If one insists both that the type be unique (as opposed to an alias for a tuple) and that the notation to create a point be Point (x, y), then the following works:
datatype point (t : t@ype+) =
| Point of (t, t)
val p : point double = Point (1.0, 3.0)
AutoHotkey
monkeypatched example.
point := Object()
point.x := 1
point.y := 0
AWK
As usual, arrays are the only data type more complex than a number or a string.
Use quotes around constant strings as element selectors:
BEGIN {
p["x"]=10
p["y"]=42
z = "ZZ"
p[ z ]=999
p[ 4 ]=5
for (i in p) print( i, ":", p[i] )
}
- Output:
4 : 5 x : 10 y : 42 ZZ : 999
Axe
Axe does not have language support for custom data structures. However, they can be implemented from scratch using memory directly.
Lbl POINT
r₂→{r₁}ʳ
r₃→{r₁+2}ʳ
r₁
Return
To initialize a POINT at memory address L₁ with (x, y) = (5, 10):
POINT(L₁,5,10)
The caller must ensure the buffer has enough free space to contain the object (in this case, 4 bytes).
BASIC
TYPE Point
x AS INTEGER
y AS INTEGER
END TYPE
BBC BASIC
DIM Point{x%, y%}
Bracmat
Normally, values are compounded by putting them in a tree structure. For examples, the values 3
and 4
can be put in a small tree (3.4)
.
But since the task requires the values to be independent, the values must be changeable, which they are not in (3.4)
.
So we go object oriented and create a 'type' Point. We show that x
and y
are independent by changing the value of x
and checking that y
didn't change.
Bracmat does not have other typing systems than duck typing. The variable Point
is not a class, but an object in its own right. The new$
function creates a copy of Point
.
( ( Point
= (x=)
(y=)
(new=.!arg:(?(its.x).?(its.y)))
)
& new$(Point,(3.4)):?pt
& out$(!(pt..x) !(pt..y))
{ Show independcy by changing x, but not y }
& 7:?(pt..x)
& out$(!(pt..x) !(pt..y))
);
- Output:
3 4 7 4
Brlcad
In brlcad, the datatypes are geometric primitives or combinations. Here we create a lamp using a combination of previously created components:
c lamp base stem bulb shade chord plug
C
typedef struct Point
{
int x;
int y;
} Point;
C#
struct Point
{
public int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
C++
struct Point
{
int x;
int y;
};
It is also possible to add a constructor (this allows the use of Point(x, y) in expressions):
struct Point
{
int x;
int y;
Point(int ax, int ay): x(ax), y(ax) {}
};
Point can also be parametrized on the coordinate type:
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 };
Of course, a constructor can be added in this case as well.
Clean
Record type
:: Point = { x :: Int, y :: Int }
Parameterized Algebraic type
:: Point a = Point a a // usage: (Point Int)
Synonym type
:: Point :== (Int, Int)
Clojure
(defrecord Point [x y])
This defines a datatype with constructor Point. and accessors :x and :y :
(def p (Point. 0 1))
(assert (= 0 (:x p)))
(assert (= 1 (:y p)))
CLU
CLU has two types of compound datatypes: structs, which are immutable, and records, which are mutable. Aside from this, they work the same way.
% Definitions
point = struct[x, y: int]
mutable_point = record[x, y: int]
% Initialization
p: point := point${x: 10, y: 20}
mp: mutable_point := mutable_point${x: 10, y: 20}
The fields can be accessed using the .
syntax:
foo := p.x
bar := p.y
Records, but not structs, allow updating the fields in the same way.
mp.x := 30
mp.y := 40
It should be noted that the special forms p.x
and mp.x := value
are really only syntactic sugar, they are equivalent to the following method calls:
foo := point$get_x(p)
bar := point$get_y(p)
mutable_point$set_x(mp, 30)
mutable_point$set_y(mp, 40)
COBOL
A compound data item description is possible in COBOL as a subdivided record:
DATA DIVISION.
WORKING-STORAGE SECTION.
01 Point.
05 x USAGE IS BINARY-SHORT.
05 y USAGE IS BINARY-SHORT.
Here the record Point
has the subdivisions x
and y
, both of which are signed 16-bit binary integers.
CoffeeScript
# Lightweight JS objects (with CS sugar).
point =
x: 5
y: 3
console.log point.x, point.y # 5 3
# Heavier OO style
class Point
constructor: (@x, @y) ->
distance_from: (p2) ->
dx = p2.x - @x
dy = p2.y - @y
Math.sqrt dx*dx + dy*dy
p1 = new Point(1, 6)
p2 = new Point(6, 18)
console.log p1 # { x: 1, y: 6 }
console.log p1.distance_from # [Function]
console.log p1.distance_from p2 # 13
Common Lisp
CL-USER> (defstruct point (x 0) (y 0)) ;If not provided, x or y default to 0
POINT
In addition to defining the point data type, the defstruct macro also created constructor and accessor functions:
CL-USER> (setf a (make-point)) ;The default constructor using the default values for x and y
#S(POINT :X 0 :Y 0)
CL-USER> (setf b (make-point :x 5.5 :y #C(0 1))) ;Dynamic datatypes are the default
#S(POINT :X 5.5 :Y #C(0 1)) ;y has been set to the imaginary number i (using the Common Lisp complex number data type)
CL-USER> (point-x b) ;The default name for the accessor functions is structname-slotname
5.5
CL-USER> (point-y b)
#C(0 1)
CL-USER> (setf (point-y b) 3) ;The accessor is setfable
3
CL-USER> (point-y b)
3
Crystal
Crystal's structs work very similarly to objects, but are allocated on the stack instead of the heap, and passed by value instead of by reference. More potential caveats are noted in the language reference.
struct Point(T)
getter x : T
getter y : T
def initialize(@x, @y)
end
end
puts Point(Int32).new 13, 12 #=> Point(Int32)(@x=13, @y=12)
D
void main() {
// A normal POD struct
// (if it's nested and it's not static then it has a hidden
// field that points to the enclosing function):
static struct Point {
int x, y;
}
auto p1 = Point(10, 20);
// It can also be parametrized on the coordinate type:
static struct Pair(T) {
T x, y;
}
// A pair with integer coordinates:
auto p2 = Pair!int(3, 5);
// A pair with floating point coordinates:
auto p3 = Pair!double(3, 5);
// Classes (static inner):
static class PointClass {
int x, y;
this(int x_, int y_) {
this.x = x_;
this.y = y_;
}
}
auto p4 = new PointClass(1, 2);
// There are also library-defined tuples:
import std.typecons;
alias Tuple!(int,"x", int,"y") PointXY;
auto p5 = PointXY(3, 5);
// And even built-in "type tuples":
import std.typetuple;
alias TypeTuple!(int, 5) p6;
static assert(is(p6[0] == int));
static assert(p6[1] == 5);
}
Delphi
As defined in Types.pas:
TPoint = record
X: Longint;
Y: Longint;
end;
Diego
use_namespace(rosettacode)_me();
add_struct(point)_arg(x,y);
with_point(point1)_arg(4,3);
// Since no datatype is specified for the args any datatype can be passed
with_point(point2)_arg(0.033,👣);
reset_namespace[];
E
def makePoint(x, y) {
def point {
to getX() { return x }
to getY() { return y }
}
return point
}
EchoLisp
(lib 'struct)
(struct Point (x y))
(Point 3 4)
→ #<Point> (3 4)
;; run-time type checking is possible
(lib 'types)
(struct Point (x y))
(struct-type Point Number Number)
(Point 3 4)
(Point 3 'albert)
❌ error: #number? : type-check failure : albert → 'Point:y'
Ela
Ela supports algebraic types:
type Maybe = None | Some a
Except of regular algebraic types, Ela also provides a support for open algebraic types - which can be extended any time with new constructors:
opentype Several = One | Two | Three
//Add new constructor to an existing type
data Several = Four
Elena
ELENA 6.x:
struct Point
{
int X : prop;
int Y : prop;
constructor new(int x, int y)
{
X := x;
Y := y
}
}
Elixir
iex(1)> defmodule Point do
...(1)> defstruct x: 0, y: 0
...(1)> end
{:module, Point, <<70, 79, 82, ...>>, %Point{x: 0, y: 0}}
iex(2)> origin = %Point{}
%Point{x: 0, y: 0}
iex(3)> pa = %Point{x: 10, y: 20}
%Point{x: 10, y: 20}
iex(4)> pa.x
10
iex(5)> %Point{pa | y: 30}
%Point{x: 10, y: 30}
iex(6)> %Point{x: px, y: py} = pa # pattern matching
%Point{x: 10, y: 20}
iex(7)> px
10
iex(8)> py
20
Elm
--Compound Data type can hold multiple independent values
--In Elm data can be compounded using List, Tuple, Record
--In a List
point = [2,5]
--This creates a list having x and y which are independent and can be accessed by List functions
--Note that x and y must be of same data type
--Tuple is another useful data type that stores different independent values
point = (3,4)
--Here we can have multiple data types
point1 = ("x","y")
point2 = (3,4.5)
--The order of addressing matters
--Using a Record is the best option
point = {x=3,y=4}
--To access
point.x
point.y
--Or Use it as a function
.x point
.y point
--Also to alter the value
{point | x=7}
{point | y=2}
{point | x=3,y=4}
--Each time a new record is generated
--END
Erlang
-module(records_test).
-compile(export_all).
-record(point,{x,y}).
test() ->
P1 = #point{x=1.0,y=2.0}, % creates a new point record
io:fwrite("X: ~f, Y: ~f~n",[P1#point.x,P1#point.y]),
P2 = P1#point{x=3.0}, % creates a new point record with x set to 3.0, y is copied from P1
io:fwrite("X: ~f, Y: ~f~n",[P2#point.x,P2#point.y]).
Euphoria
enum x, y
sequence point = {0,0}
printf(1,"x = %d, y = %3.3f\n",point)
point[x] = 'A'
point[y] = 53.42
printf(1,"x = %d, y = %3.3f\n",point)
printf(1,"x = %s, y = %3.3f\n",point)
- Output:
x = 0, y = 0.000 x = 65, y = 53.420 x = A, y = 53.420
F#
See the OCaml section as well. Here we create a list of points and print them out.
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
Factor
TUPLE: point x y ;
Fantom
// define a class to contain the two fields
// accessors to get/set the field values are automatically generated
class Point
{
Int x
Int y
}
class Main
{
public static Void main ()
{
// empty constructor, so x,y set to 0
point1 := Point()
// constructor uses with-block, to initialise values
point2 := Point { x = 1; y = 2}
echo ("Point 1 = (" + point1.x + ", " + point1.y + ")")
echo ("Point 2 = (" + point2.x + ", " + point2.y + ")")
}
}
- Output:
Point 1 = (0, 0) Point 2 = (1, 2)
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
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
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
FreeBASIC
' FB 1.05.0 Win64
Type Point
As Integer x, y
End Type
Dim p As Point = (1, 2)
Dim p2 As Point = (3, 4)
Print p.x, p.y
Print p2.x, p2.y
Sleep
- Output:
1 2 3 4
FutureBasic
CGRect r = {0, 0, 250, 100}
printf @"x = %.f : y = %.f : width = %.f : height = %.f", r.origin.x, r.origin.y, r.size.width, r.size.height
HandleEvents
- Output:
x = 0 : y = 0 : width = 250 : height = 100
Go
type point struct {
x, y float64
}
Groovy
Declaration
class Point {
int x
int y
// Default values make this a 0-, 1-, and 2-argument constructor
Point(int x = 0, int y = 0) { this.x = x; this.y = y }
String toString() { "{x:${x}, y:${y}}" }
}
Instantiation
Direct
// Default Construction with explicit property setting:
def p0 = new Point()
assert 0 == p0.x
assert 0 == p0.y
p0.x = 36
p0.y = -2
assert 36 == p0.x
assert -2 == p0.y
// Direct Construction:
def p1 = new Point(36, -2)
assert 36 == p1.x
assert -2 == p1.y
def p2 = new Point(36)
assert 36 == p2.x
assert 0 == p2.y
List-to-argument Substitution
There are several ways that a List can be substituted for constructor arguments via "type coercion" (casting).
// Explicit coersion from list with "as" keyword
def p4 = [36, -2] as Point
assert 36 == p4.x
assert -2 == p4.y
// Explicit coersion from list with Java/C-style casting
p4 = (Point) [36, -2]
println p4
assert 36 == p4.x
assert -2 == p4.y
// Implicit coercion from list (by type of variable)
Point p6 = [36, -2]
assert 36 == p6.x
assert -2 == p6.y
Point p8 = [36]
assert 36 == p8.x
assert 0 == p8.y
Map-to-property Substitution
There are several ways to construct an object using a map (or a comma-separated list of map entries) that substitutes entries for class properties. The process is properly (A) instantiation, followed by (B) property mapping. Because the instantiation is not tied to the mapping, it requires the existence of a no-argument constructor.
// Direct map-based construction
def p3 = new Point([x: 36, y: -2])
assert 36 == p3.x
assert -2 == p3.y
// Direct map-entry-based construction
p3 = new Point(x: 36, y: -2)
assert 36 == p3.x
assert -2 == p3.y
p3 = new Point(x: 36)
assert 36 == p3.x
assert 0 == p3.y
p3 = new Point(y: -2)
assert 0 == p3.x
assert -2 == p3.y
// Explicit coercion from map with "as" keyword
def p5 = [x: 36, y: -2] as Point
assert 36 == p5.x
assert -2 == p5.y
// Implicit coercion from map (by type of variable)
Point p7 = [x: 36, y: -2]
assert 36 == p7.x
assert -2 == p7.y
Point p9 = [y:-2]
assert 0 == p9.x
assert -2 == p9.y
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 a special case of the 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:
p = (2,3)
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
IDL
point = {x: 6 , y: 0 }
point.y = 7
print, point
;=> { 6 7}
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:
NB. Create a "Point" class
coclass'Point'
NB. Define its constructor
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
Jakt
struct Point {
x: i64
y: i64
}
fn main() {
println("{}", Point(x: 3, y: 4))
}
Java
Starting with Java 14 you can use a record
record Point(int x, int y) { }
Usage
Point point = new Point(1, 2);
int x = point.x;
int y = point.y;
Alternately
We use a class:
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 );
}
}
JavaScript
//using object literal syntax
var point = {x : 1, y : 2};
//using constructor
var Point = function (x, y) {
this.x = x;
this.y = y;
};
point = new Point(1, 2);
//using ES6 class syntax
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
point = new Point(1, 2);
jq
{"x":1, "y":2}
If the emphasis in the task description is on "type", then an alternative approach would be to include a "type" key, e.g.
{"x":1, "y":2, type: "Point"}
Using this approach, one can distinguish between objects of type "Point" and those that happen to have keys named "x" and "y".
JSON
{"x":1,"y":2}
Julia
Define the type:
struct Point{T<:Real}
x::T
y::T
end
The components of Point
can be any sort of real number, though they do have to be of the same type.
Define a few simple operations for Point:
Base.:(==)(u::Point, v::Point) = u.x == v.x && u.y == v.y
Base.:-(u::Point) = Point(-u.x, -u.y)
Base.:+(u::Point, v::Point) = Point(u.x + v.x, u.y + v.y)
Base.:-(u::Point, v::Point) = u + (-v)
Have fun:
a, b, c = Point(1, 2), Point(3, 7), Point(2, 4)
@show a b c
@show a + b
@show -a + b
@show a - b
@show a + b + c
@show a == b
@show a + a == c
- Output:
a = Point{Int64}(1, 2) b = Point{Int64}(3, 7) c = Point{Int64}(2, 4) a + b = Point{Int64}(4, 9) -a + b = Point{Int64}(2, 5) a - b = Point{Int64}(-2, -5) a + b + c = Point{Int64}(6, 13) a == b = false a + a == c = true
KonsolScript
Var:Create(
Point,
Number x,
Number y
)
Instanciate it with...
function main() {
Var:Point point;
}
Kotlin
data class Point(var x: Int, var y: Int)
fun main(args: Array<String>) {
val p = Point(1, 2)
println(p)
p.x = 3
p.y = 4
println(p)
}
- Output:
Point(x=1, y=2) Point(x=3, y=4)
Lambdatalk
1) a pair
{def P {P.new 1 2}}
-> P
{P.left {P}}
-> 1
{P.right {P}}
-> 2
2) its Lispsish variant
{def Q {cons 1 2}}
-> Q
{car {Q}}
-> 1
{cdr {Q}}
-> 2
3) as an array
{def R {A.new 1 2}}
-> R
{A.first {R}}
-> 1
{A.last {R}}
-> 2
Lang
&Point = {
$x
$y
}
Lasso
In Lasso, a point could just be stored in the pair type. However, assuming we want to be able to access the points using the member methods [Point->x] and [Point->y], let's just create a type that inherits from the pair type:
define Point => type {
parent pair
public onCreate(x,y) => {
..onCreate(#x=#y)
}
public x => .first
public y => .second
}
local(point) = Point(33, 42)
#point->x
#point->y
- Output:
33 43
LFE
Simply define a record in the LFE REPL (can also be used in include files, modules, etc.):
(defrecord point
x
y)
Creating points:
> (make-point x 0 y 0) #(point 0 0) > (set p (make-point x 1.1 y -4.2)) #(point 1.1 -4.2)
Accessing:
> (point-x p) 1.1 > (point-y p) -4.2
Updates (note that since LFE has no mutable data, persisted updates would need to rebind the new value to the old variable name):
> (set-point-x p 3.1) #(point 3.1 -4.2) > (set-point-y p 4.2) #(point 1.1 4.2)
Metadata, etc.:
> (fields-point) (x y) > (is-point #(x y)) false > (is-point p) true
Lingo
Point and Vector types are built-in. A custom "MyPoint" type can be implemented like this:
-- parent script "MyPoint"
property x
property y
on new (me, px, py)
me.x = px
me.y = py
return me
end
p = script("MyPoint").new(23, 42)
put p.x, p.y
-- 23 42
Construction could also be simplified by using a global wrapper function:
-- in some movie script
on MyPoint (x, y)
return script("MyPoint").new(x, y)
end
p = MyPoint(23, 42)
put p.x, p.y
-- 23 42
Logo
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]
Lua
Simple Table
Lua could use a simple table to store a compound data type Point(x, y):
a = {x = 1; y = 2}
b = {x = 3; y = 4}
c = {
x = a.x + b.x;
y = a.y + b.y
}
print(a.x, a.y) --> 1 2
print(c.x, c.y) --> 4 6
Prototype Object
Furthermore, Lua could create a prototype object (OOP class emulation) to represent a compound data type Point(x, y) as the following:
cPoint = {} -- metatable (behaviour table)
function newPoint(x, y) -- constructor
local pointPrototype = {} -- prototype declaration
function pointPrototype:getX() return x end -- public method
function pointPrototype:getY() return y end -- public method
function pointPrototype:getXY() return x, y end -- public method
function pointPrototype:type() return "point" end -- public method
return setmetatable(pointPrototype, cPoint) -- set behaviour and return the pointPrototype
end--newPoint
In the above example, the methods are declared inside the constructor so that they could access the closured values x
and y
(see usage example). The pointPrototype:type
method could be used to extend the original type
function available in Lua:
local oldtype = type; -- store original type function
function type(v)
local vType = oldtype(v)
if (vType=="table" and v.type) then
return v:type() -- bypass original type function if possible
else
return vType
end--if vType=="table"
end--type
The usage of metatable cPoint
which stores the behavior of the pointPrototype
enables additional behaviour to be added to the data type, such as:
function cPoint.__add(op1, op2) -- add the x and y components
if type(op1)=="point" and type(op2)=="point" then
return newPoint(
op1:getX()+op2:getX(),
op1:getY()+op2:getY())
end--if type(op1)
end--cPoint.__add
function cPoint.__sub(op1, op2) -- subtract the x and y components
if (type(op1)=="point" and type(op2)=="point") then
return newPoint(
op1:getX()-op2:getX(),
op1:getY()-op2:getY())
end--if type(op1)
end--cPoint.__sub
Usage example:
a = newPoint(1, 2)
b = newPoint(3, 4)
c = a + b -- using __add behaviour
print(a:getXY()) --> 1 2
print(type(a)) --> point
print(c:getXY()) --> 4 6
print((a-b):getXY()) --> -2 -2 -- using __sub behaviour
Maple
Point:= Record(x = 2,y = 4):
Point:-x;
Point:-y;
- Output:
2 4
Mathematica / Wolfram Language
Expressions like point[x, y] can be used without defining.
In[1]:= a = point[2, 3]
Out[1]= point[2, 3]
In[2]:= a[[2]]
Out[2]= 3
In[3]:= a[[2]] = 4; a
Out[3]= point[2, 4]
Or you can just define a function.
p[x] = 2; p[y] = 3;
Data will be stored as down values of the symbol p.
MATLAB / Octave
point.x=3;
point.y=4;
Alternatively, coordinates can be also stored as vectors
point = [3,4];
Maxima
defstruct(point(x, y))$
p: new(point)$
q: point(1, 2)$
p@x: 5$
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
MiniScript
Point = {}
Point.x = 0
Point.y = 0
Modula-2
TYPE Point = RECORD
x, y : INTEGER
END;
Usage:
VAR point : Point;
...
point.x := 12;
point.y := 7;
Modula-3
TYPE Point = RECORD
x, y: INTEGER;
END;
Usage:
VAR point: Point; ... point := Point{3, 4};
or
point := Point{x := 3, y := 4};
NetRexx
Like Java, NetRexx uses the class instruction to create compound types. Unlike Java; NetRexx provides keywords to automatically generate getters and setters for class properties and will automatically generate intermediate methods based on defaults provided in method prototypes.
/* NetRexx */
options replace format comments java crossref symbols nobinary
class RCompoundDataType
method main(args = String[]) public static
pp = Point(2, 4)
say pp
return
class RCompoundDataType.Point -- inner class "Point"
properties indirect -- have NetRexx create getters & setters
x = Integer
y = Integer
method Point(x_ = 0, y_ = 0) public -- providing default values for x_ & y_ lets NetRexx generate intermediate constructors Point() & Point(x_)
this.x = Integer(x_)
this.y = Integer(y_)
return
method toString() public returns String
res = 'X='getX()',Y='getY()
return res
- Output:
X=2,Y=4
Nim
type Point = tuple[x, y: int]
var p: Point = (12, 13)
var p2: Point = (x: 100, y: 200)
Oberon-2
MODULE Point;
TYPE
Object* = POINTER TO ObjectDesc;
ObjectDesc* = RECORD
x-,y-: INTEGER;
END;
PROCEDURE (p: Object) Init(x,y: INTEGER);
BEGIN
p.x := x; p.y := y
END Init;
PROCEDURE New*(x,y: INTEGER): Object;
VAR
p: Object;
BEGIN
NEW(p);p.Init(x,y);RETURN p;
END New;
END Point.
Objeck
Classes are used for compound data types.
class Point {
@x : Int;
@y : Int;
New() {
@x := 0;
@y := 0;
}
New(x : Int, y : Int) {
@x := x;
@y := y;
}
New(p : Point) {
@x := p->GetX();
@y := p->GetY();
}
method : public : GetX() ~ Int {
return @x;
}
method : public : GetY() ~ Int {
return @y;
}
method : public : SetX(x : Int) ~ Nil {
@x := x;
}
method : public : SetY(y : Int) ~ Nil {
@y := y;
}
}
OCaml
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; multiple arguments are declared with a syntax that looks like a tuple type, but it is not really a tuple.
type tree = Empty
| Leaf of int
| Node of tree * tree
let t1 = Node (Leaf 1, Node (Leaf 2, Leaf 3))
Record Type
type point = { x : int; y : int }
How to construct a point:
let p = { x = 4; y = 5 }
You can use the dot (".") to access fields.
p.x (* evaluates to 4 *)
Fields can be optionally declared to be mutable:
type mutable_point = { mutable x2 : int; mutable y2 : int }
Then they can be assigned using the assignment operator "<-"
let p2 = { x2 = 4; y2 = 5 } in
p2.x2 <- 6;
p2 (* evaluates to { x2 = 6; y2 = 5 } *)
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:
let p = (2,3)
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)
Oforth
Using a class :
Object Class new: Point(x, y)
ooRexx
ooRexx uses class for compound data types.
p = .point~new(3,4)
say "x =" p~x
say "y =" p~y
::class point
::method init
expose x y
use strict arg x = 0, y = 0 -- defaults to 0 for any non-specified coordinates
::attribute x
::attribute y
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.
OxygenBasic
'SHORT FORM
type point float x,y
'FULL FORM
type point
float x
float y
end type
point p
'WITH DEFAULT VALUES
type point
float x = 1.0
float y = 1.0
end type
point p = {} 'assigns the set of default values
print p.x " " p.y
Oz
A point can be represented by using a record value:
P = point(x:1 y:2)
Now we can access the components by name: P.x and P.y Often such values are deconstructed by pattern matching:
case P of point(x:X y:Y) then
{Show X}
{Show Y}
end
PARI/GP
point.x=1;
point.y=2;
Pascal
type point = record
x, y: integer;
end;
PascalABC.NET
Classes in PascalABC.NET are reference types and records are value types.
type
Point = class
x,y: integer;
constructor(x,y: integer) := (Self.x,Self.y) := (x,y);
end;
PointRec = record
x,y: integer;
constructor(x,y: integer) := (Self.x,Self.y) := (x,y);
end;
begin
var p := new Point(2,3);
Println(p.x,p.y);
var pr := new PointRec(4,5);
Println(pr.x,pr.y);
end.
Perl
Array
my @point = (3, 8);
Hash
my %point = (
x => 3,
y => 8
);
Class instance
package Point;
use strict;
use base 'Class::Struct'
x => '$',
y => '$',
;
my $point = Point->new(x => 3, y => 8);
Phix
traditional user defined type
The sequence is a natural compound data type. The following would be the same without the type point and declaring p as a sequence, apart from the run-time error. There would be no difficulty defining point to have a string and two atoms.
with javascript_semantics enum x,y type point(object p) return sequence(p) and length(p)=y and atom(p[x]) and atom(p[y]) end type point p = {175,3.375} p[x] -= p[y]*20 puts(1,"point p is ") ?p printf(1,"p[x]:%g, p[y]:%g\n",{p[x],p[y]}) p[x] = 0 -- fine p[y] = "string" -- run-time error (not pwa/p2js)
- Output:
point p is {107.5,3.375} p[x]:107.5, p[y]:3.375 C:\Program Files (x86)\Phix\test.exw:12 type check failure, p is {0,"string"} --> see C:\Program Files (x86)\Phix\ex.err Press Enter...
classes
You could also use a class (not pwa/p2js)
class point public atom x,y end class point p = new({175,3.375}) p.x -= p.y*20 printf(1,"p.x:%g, p.y:%g\n",{p.x,p.y}) p.x = 0 -- fine p.y = "string" -- run-time error
- Output:
p.x:107.5, p.y:3.375 C:\Program Files (x86)\Phix\test.exw:9 type error assigning "string" to point.y --> see C:\Program Files (x86)\Phix\ex.err Press Enter...
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;
# Using array
$point = array('x' => 1, 'y' => 2);
list($x, $y) = $point;
echo $x, ' ', $y, "\n";
# or simply:
echo $point['x'], ' ', $point['y'], "\n";
# 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.
PicoLisp
(class +Point)
(dm T (X Y)
(=: x X)
(=: y Y) )
(setq P (new '(+Point) 3 4))
(show P)
- Output:
$52717735311266 (+Point) y 4 x 3
Pike
class Point {
int x, y;
void create(int _x, int _y)
{
x = _x;
y = _y;
}
}
void main()
{
object point = Point(10, 20);
write("%d %d\n", point->x, point->y);
}
- Output:
10 20
PL/I
define structure
1 point,
2 x float,
2 y float;
Plain English
A cartesian point is a record with an x coord and a y coord.
Pop11
uses objectclass;
define :class Point;
slot x = 0;
slot y = 0;
enddefine;
PowerShell
class Point {
[Int]$a
[Int]$b
Point() {
$this.a = 0
$this.b = 0
}
Point([Int]$a, [Int]$b) {
$this.a = $a
$this.b = $b
}
[Int]add() {return $this.a + $this.b}
[Int]mul() {return $this.a * $this.b}
}
$p1 = [Point]::new()
$p2 = [Point]::new(3,2)
$p1.add()
$p2.mul()
Output:
0 6
Prolog
Prolog terms ARE compound data types, there is no need to specifically define a type. for the purpose of this exercise you could define a rule like so:
point(10, 20).
This will create static point that can be called:
?- point(X,Y).
X = 10,
Y = 20.
terms can be passed around as values and can have a complex nested structure of any size, eg:
person_location(person(name(N), age(A)), point(X, Y)).
PureBasic
A basic structure is implemented as;
Structure MyPoint
x.i
y.i
EndStructure
Python
The simplest way it to use a tuple, or a list if it should be mutable:
X, Y = 0, 1
p = (3, 4)
p = [3, 4]
print p[X]
If needed, you can use class:
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
p = Point()
print p.x
One could also simply instantiate a generic object and "monkeypatch" it:
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
Dictionary
Mutable. Can add keys (attributes)
pseudo_object = {'x': 1, 'y': 2}
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.
>>> 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)
>>>
QB64
Type Point
x As Double
y As Double
End Type
Dim p As Point
p.x = 15.42
p.y = 2.412
Print p.x; p.y
- Output:
15.42 2.412
Quackery
The single ubiquitous compound data type in Quackery is the nest (a mostly immutable dynamic array), a sequence of items wrapped in square brackets. (Mostly immutable; i.e. immutable except under limited circumstances beyond the scope of this discussion. When we refer to changing the contents of a nest here, this is casual speech; a shorthand for saying "creating a new instance of the nest, identical the previous instance except where it differs".)
Presented here are two solutions to the task, the "quick and dirty" solution; sufficient to the task described here, and the "overkill" solution; extending the Quackery compiler to facilitate complex compound data structures akin to structs in C etc.
Quick and Dirty
The word point
creates an instance of a nest with two elements, both initialised to zero. The word x
specifies the location of the zeroth element within the nest, and the word y
specifies the location of the first element within the nest. peek
returns the value stored in a specified location, and poke
changes the value stored in a specified location, returning the modified nest.
[ ' [ 0 0 ] ] is point ( --> [ )
[ 0 ] is x ( --> n )
[ 1 ] is y ( --> n )
point
dup x peek echo cr
99 swap y poke
y peek echo cr
- Output:
0 99
Overkill
The "overkill" solution automates the process of creating new structures with the word struct{
, which extends the Quackery compiler to allow the definition of complex compound data structures as follows.
struct{
item.0
{ item.1.0
item.1.1
{ item.1.2.0
item.1.2.1
item.1.2.2
item.1.2.3
} item.1.2
item.1.3
} item.1
item.2
}struct mystruct
Once defined, the word mystruct
will place a new instance of the described structure, with each item initialised to null
, on the stack. (The behaviour of null
is to place a reference to itself on the stack, as a convenience for debugging, and to allow code to identify elements within the structure that have not had a value assigned to them.)
The various names defined within the struct (e.g. item.1.2.1
) return a path - a means of locating a specific item within the struct, for use by {peek}
and {poke}
, which have the same behaviours as peek
and poke
, except the they take a path to an item within a struct as an argument, rather than a number specifying an item within a nest.
Names following a }
within the definition of a struct (e.g. } item.1.2
) return a path to the compound data structure preceding it within the structure. In the example, item.1.2
returns the path to { item.1.2.0 item.1.2.1 item.1.2.2 item.1.2.3 }
mystruct ( create new instance of a mystruct )
dup echo cr ( this is what it looks like )
789 swap item.1.3 {poke} ( change one of the items )
dup echo cr ( this is what it looks like now )
item.1.3 {peek} echo cr ( retrieve the specified item )
- Output:
[ null [ null null [ null null null null ] null ] null ] [ null [ null null [ null null null null ] 789 ] null ] 789
The words {peek}
, {poke}
, null
, and the building word (i.e. compiler extension) struct{
defined:
[ witheach peek ] is {peek} ( { p --> x )
[ dip dup
witheach [ peek dup ]
drop ] is depack ( { p --> * )
[ reverse
witheach
[ dip swap poke ] ] is repack ( * p --> { )
[ dup dip
[ rot dip
[ depack drop ] ]
repack ] is {poke} ( x { p --> { )
[ this ] is null ( --> [ )
[ stack ] is {}.path ( --> s )
protect {}.path
[ stack ] is {}.struct ( --> s )
protect {}.struct
[ nextword dup
$ "" = if
[ $ "Unexpected end of struct."
message put
bail ] ] is {}.checknext ( [ $ --> [ $ $ )
[ dup $ "{" =
over $ "}" = or
swap $ "}struct" = or if
[ $ "Name missing after }."
message put
bail ] ] is {}.checkname ( [ $ $ --> [ $ )
[ nested
namenest take
join
namenest put
' [ ' ]
{}.path share nested join
actiontable take
1 stuff
actiontable put ] is {}.addpath ( [ $ $ --> [ $ )
[ nested
namenest take
join
namenest put
' [ ' ]
{}.struct share nested join
actiontable take
1 stuff
actiontable put ] is {}.addstruct ( [ $ $ --> [ $ )
[ {}.path take
dup -1 peek
1+
swap -1 poke
-1 join
{}.path put
[] {}.struct put ] is {}.{ ( [ $ --> [ $ )
[ {}.struct size 3 < if
[ $ "Badly formed struct."
message put bail ]
trim {}.checknext
dup {}.checkname
{}.path take
-1 split drop
{}.path put
{}.addpath
{}.struct take
{}.struct take
swap nested join
{}.struct put ] is {}.} ( [ $ --> [ $ )
[ {}.path take
dup -1 peek
1+
swap -1 poke
{}.path put
{}.addpath
{}.struct take
' [ null ] join
{}.struct put ] is {}.name ( [ $ --> [ $ )
[ trim {}.checknext
{}.struct size
2 != if
[ $ "Badly formed struct."
message put
bail ]
{}.addstruct ] is {}.}struct ( [ $ --> [ $ )
[ ' [ -1 ] {}.path put
[] {}.struct put
[ trim {}.checknext
dup $ "{" = iff
[ drop {}.{ ] again
dup $ "}" = iff
[ drop {}.} ] again
dup $ "}struct" = iff
[ drop {}.}struct ] done
{}.name again ]
{}.struct release
{}.path release ] builds struct{ ( [ $ --> [ $ )
Finally we use struct{
etc. to fulfil the requirements go the task.
struct{ x y }struct point
point
dup x {peek} echo cr
99 swap y {poke}
y {peek} echo cr
- Output:
null 99
R
R uses the list data type for compound data.
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
Racket
The most common method uses structures (similar to records):
#lang racket
(struct point (x y))
Alternatively, you can define a class:
#lang racket
(define point% ; classes are suffixed with % by convention
(class object%
(super-new)
(init-field x y)))
Raku
(formerly Perl 6)
Array
my @point = 3, 8;
my Int @point = 3, 8; # or constrain to integer elements
Hash
my %point = x => 3, y => 8;
my Int %point = x => 3, y => 8; # or constrain the hash to have integer values
Class instance
class Point { has Real ($.x, $.y) is rw; }
my Point $point .= new: x => 3, y => 8;
Set
my $s1 = set <a b c d>; # order is not preserved
my $s2 = set <c d e f>;
say $s1 (&) $s2; # OUTPUT«set(c, e)»
say $s1 ∩ $s2; # we also do Unicode
REXX
x= -4.9
y= 1.7
point=x y
- ---or---
x= -4.1
y= 1/4e21
point=x y
bpoint=point
gpoint=5.6 7.3e-12
Ring
see new point {x=10 y=20} class point x y
Output
x: 10.000000
y: 20.000000
Ruby
Point = Struct.new(:x,:y)
pt = Point.new(6,7)
puts pt.x #=> 6
pt.y = 3
puts pt #=> #<struct Point x=6, y=3>
# The other way of accessing
pt = Point[2,3]
puts pt[:x] #=> 2
pt['y'] = 5
puts pt #=> #<struct Point x=2, y=5>
pt.each_pair{|member, value| puts "#{member} : #{value}"}
#=> x : 2
#=> y : 5
Rust
Structs
There are three kinds of struct
s in Rust, two of which would be suitable to represent a point.
C-like struct
// Defines a generic struct where x and y can be of any type T
struct Point<T> {
x: T,
y: T,
}
fn main() {
let p = Point { x: 1.0, y: 2.5 }; // p is of type Point<f64>
println!("{}, {}", p.x, p.y);
}
Tuple struct
These are basically just named tuples.
struct Point<T>(T, T);
fn main() {
let p = Point(1.0, 2.5);
println!("{},{}", p.0, p.1);
}
Tuples
fn main() {
let p = (0.0, 2.4);
println!("{},{}", p.0, p.1);
}
Scala
case class Point(x: Int = 0, y: Int = 0)
val p = Point(1, 2)
println(p.y) //=> 2
Scheme
Using SRFI 9:
(define-record-type point
(make-point x y)
point?
(x point-x)
(y point-y))
Seed7
const type: Point is new struct
var integer: x is 0;
var integer: y is 0;
end struct;
Shen
(datatype point
X : number; Y : number;
====================
[point X Y] : point;)
Pairs (distinct from cons cells) are also supported, in which case a point would be denoted by (number * number):
(2+) (@p 1 2)
(@p 1 2) : (number * number)
Sidef
struct Point {x, y};
var point = Point(1, 2);
say point.y; #=> 2
SIMPOL
The point
type is pre-defined in [SIMPOL], so we will call this mypoint.
type mypoint
embed
integer x
integer y
end type
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.
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
SNOBOL4
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
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.
datatype tree = Empty
| Leaf of int
| Node of tree * tree
val t1 = Node (Leaf 1, Node (Leaf 2, Leaf 3))
Tuple Type
You can make a tuple literal by using a comma-delimited list surrounded by parentheses, without needing to declare the type first:
val p = (2,3)
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:
val p = { x = 4, y = 5 }
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.
Stata
See struct in Stata help.
mata
struct Point {
real scalar x, y
}
// dumb example
function test() {
struct Point scalar a
a.x = 10
a.y = 20
printf("%f\n",a.x+a.y)
}
test()
30
end
Swift
// Structure
struct Point {
var x:Int
var y:Int
}
// Tuple
typealias PointTuple = (Int, Int)
// Class
class PointClass {
var x:Int!
var y:Int!
init(x:Int, y:Int) {
self.x = x
self.y = y
}
}
Tcl
This can be done using an associative array:
array set point {x 4 y 5}
set point(y) 7
puts "Point is {$point(x),$point(y)}"
# => Point is {4,7}
Or a dictionary:
set point [dict create x 4 y 5]
dict set point y 7
puts "Point is {[dict get $point x],[dict get $point y]}"
Or an object:
oo::class create Point {
variable x y
constructor {X Y} {set x $X;set y $Y}
method x {args} {set x {*}$args}
method y {args} {set y {*}$args}
method show {} {return "{$x,$y}"}
}
Point create point 4 5
point y 7
puts "Point is [point show]"
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.
Transd
#lang transd
// If the Point type needs encapsulation and/or methods, it should be
// implemented as class. Otherwise, the named tuple will do.
class Point: {
x: Double(), y: Double(),
@init: (λ _x Double() _y Double() (= x _x) (= y _y)),
@to-String: (λ ss StringStream() (textout to: ss
"Point( x: " x "; y: " y " )"))
// ... other methods can be defined here ...
}
MainModule: {
Point2: typealias(Tuple<Double Double>()),
_start: (λ
(with pt Point(2.5 3.7)
(lout "Class: " pt)
)
(with pt Point2(2.5 3.7)
(lout "\nNamed tuple: " pt)
)
)
}
- Output:
Class: Point( x: 2.5; y: 3.7 ) Named tuple: [[2.5, 3.7]]
TXR
In TXR Lisp, a structure type can be created:
(defstruct point nil (x 0) (y 0))
If it is okay for the coordinates to be initialized to nil, it can be condensed to:
(defstruct point nil x y)
The nil denotes that a point has no supertype: it doesn't inherit from anything.
This structure type can then be instantiated using the new macro (not the only way):
(new point) ;; -> #S(point x 0 y 0)
(new point x 1) ;; -> #S(point x 1 y 0)
(new point x 1 y 1) ;; -> #S(point x 1 y 1)
A structure can support optional by-order-of-arguments ("boa") construction by providing a "boa constructor". The defstruct syntactic sugar does this if a function-like syntax is used in place of the structure name:
(defstruct (point x y) nil (x 0) (y 0))
The existing construction methods continue to work, but in addition, this is now possible:
(new (point 3 4)) -> #S(point x 3 y 4)
Slot access syntax is supported. If variable p holds a point, then p.x designates the x slot, as a syntactic place which can be accessed and stored:
(defun displace-point-destructively (p delta)
(inc p.x delta.x)
(inc p.y delta.y))
UNIX Shell
ksh93 allows you to define new compound types with the typeset -T command.
typeset -T Point=(
typeset x
typeset y
)
Point p
p.x=1
p.y=2
echo $p
echo ${p.x} ${p.y}
Point q=(x=3 y=4)
echo ${q.x} ${q.y}
- Output:
( x=1 y=2 ) 1 2 3 4
You can also declare compound variables "on the fly" without using a defined type:
point=()
point.x=5
point.y=6
echo $point
echo ${point.x} ${point.y}
- Output:
( x=5 y=6 ) 5 6
Ursala
A record type with two untyped fields named x
and y
can be declared like this.
point :: x y
A constant instance of the record can be declared like this.
p = point[x: 'foo',y: 'bar']
A function returning a value of this type can be defined like this,
f = point$[x: g,y: h]
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.
t = ~x p
u = ~y p
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.
Vala
struct Point {
int x;
int y;
}
VBA
Type point
x As Integer
y As Integer
End Type
Vim Script
One cannot create new data types in Vim Script. A point could be represented by a dictionary:
function MakePoint(x, y) " 'Constructor'
return {"x": a:x, "y": a:y}
endfunction
let p1 = MakePoint(3, 2)
let p2 = MakePoint(-1, -4)
echon "Point 1: x = " p1.x ", y = " p1.y "\n"
echon "Point 2: x = " p2.x ", y = " p2.y "\n"
- Output:
Point 1: x = 3, y = 2 Point 2: x = -1, y = -4
Visual Basic .NET
Structures
A simple structure with two public, mutable fields:
Structure Point
Public X, Y As Integer
End Structure
Immutable Structures
It is generally recommended in .NET that mutable structures only be used in niche cases where they provide needed performance, e.g. when the creation of massive numbers of class instances would cause excessive garbage collection pressure, as high-performance code dealing with structs generally is of a paradigm considered "impure" from an object-oriented perspective that relies on passing by reference and directly exposing fields.
The semantics of value types in .NET mean that a new copy of a structure is created whenever one is passed by value to or from a method or property. This is particularly vexing when properties are involved, as it is not possible to mutate a structure that is returned by a property, due to the returned structure actually being an independent copy of whatever the property originally returned. The only workaround would be to store the value of the property in a temporary variable, mutate that variable, and assign the mutated variable back to the property, which involves another copy operation. When a structure is large, this copying can significantly affect performance.
On another note, algorithms relying on immutable data structures are often more easily parallelized, as they eliminate the race conditions caused by concurrent reading and writing.
Below is the same Point
as above, except with an immutable API.
Structure ImmutablePoint
ReadOnly Property X As Integer
ReadOnly Property Y As Integer
Public Sub New(x As Integer, y As Integer)
Me.X = x
Me.Y = y
End Sub
End Structure
V (Vlang)
Vlang also supports embedding structs into other structs and assigning methods to structs.
struct Point {
x int
y int
}
// main() declaration can be skipped in one file programs
// we can define whether immutable or mutable by using the "mut" keyword
mut p := Point{
x: 10
y: 20
}
// struct fields are accessed using a dot
println("Value of p.x is: $p.x")
println("Show the struct:\n $p")
// alternative literal syntax can be used for structs with 3 fields or fewer
p = Point{30, 40}
assert p.x == 30
println("Show the struct again after change:\n $p")
- Output:
Value of p.x is: 10 Show the struct: Point{ x: 10 y: 20 } Show the struct again after change: Point{ x: 30 y: 40 }
Wren
class Point {
construct new(x, y) {
_x = x
_y = y
}
x { _x }
y { _y }
// for illustration allow Points to be mutated
x=(value) { _x = value }
y=(value) { _y = value }
toString { "(%(_x), %(_y))" }
}
var p = Point.new(1, 2)
System.print(p.toString)
// mutate Point object
p.x = 2
p.y = 3
// print without using the toString method
System.printAll(["(", p.x, ", ", p.y, ")"])
- Output:
(1, 2) (2, 3)
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>
Z80 Assembly
We'll declare the following C struct:
struct Point{
char x;
char y;
}
and then execute the following C code as Z80 Assembly below.
struct Point myPoint;
myPoint.x = 3;
myPoint.y = 5;
;I'm arbitrarily choosing &1100 as the memory location of our Point variable.
ld hl,&1100
ld (hl),3
inc hl
ld (hl),5
ret
zkl
The OO solution:
class Point{ var x,y;
fcn init(x,y){self.x=x.toFloat(); self.y=y.toFloat(); }
fcn toString{ "P(%f,%f)".fmt(x,y) }
fcn __opADD(P){} //+: add Point, constant or whatever
//... __opEQ == etc
}
Point(1,2).println() //-->P(1.000000,2.000000)
which can be pretty heavy weight. [read only] lists can work just as well:
point:=T(1,2); points:=T( T(1,2), L(3,4) )
zonnon
{ref,public} (* class *)
Point = object(ord,abs: integer)
var
(* instance variables *)
{public,immutable} x,y: integer;
(* method *)
procedure {public} Ord():integer;
begin
return y
end Ord;
(* method *)
procedure {public} Abs():integer;
begin
return x
end Abs;
(* constructor *)
begin
self.x := ord;
self.y := abs;
end Point;
- Programming Tasks
- RBasic language learning
- Data Structures
- 11l
- ACL2
- 6502 Assembly
- Action!
- Action! Tool Kit
- ActionScript
- Ada
- ALGOL 68
- ALGOL W
- AmigaE
- ARM Assembly
- Arturo
- ATS
- AutoHotkey
- AWK
- Axe
- BASIC
- BBC BASIC
- Bracmat
- Brlcad
- C
- C sharp
- C++
- Clean
- Clojure
- CLU
- COBOL
- CoffeeScript
- Common Lisp
- Crystal
- D
- Delphi
- Diego
- E
- EchoLisp
- Ela
- Elena
- Elixir
- Elm
- Erlang
- Euphoria
- F Sharp
- Factor
- Fantom
- Forth
- Fortran
- FreeBASIC
- FutureBasic
- Go
- Groovy
- Haskell
- Icon
- Unicon
- IDL
- J
- Jakt
- Java
- JavaScript
- Jq
- JSON
- Julia
- KonsolScript
- Kotlin
- Lambdatalk
- Lang
- Lasso
- LFE
- Lingo
- Logo
- Lua
- Maple
- Mathematica
- Wolfram Language
- MATLAB
- Octave
- Maxima
- MAXScript
- MiniScript
- Modula-2
- Modula-3
- NetRexx
- Nim
- Oberon-2
- Objeck
- OCaml
- Oforth
- OoRexx
- OpenEdge/Progress
- OxygenBasic
- Oz
- PARI/GP
- Pascal
- PascalABC.NET
- Perl
- Phix
- Phix/Class
- PHP
- PicoLisp
- Pike
- PL/I
- Plain English
- Pop11
- PowerShell
- Prolog
- PureBasic
- Python
- QB64
- Quackery
- R
- Racket
- Raku
- REXX
- Ring
- Ruby
- Rust
- Scala
- Scheme
- Seed7
- Shen
- Sidef
- SIMPOL
- SNOBOL4
- Standard ML
- Stata
- Swift
- Tcl
- TI-89 BASIC
- Transd
- TXR
- UNIX Shell
- Ursala
- Vala
- VBA
- Vim Script
- Visual Basic .NET
- V (Vlang)
- Wren
- XSLT
- Z80 Assembly
- Zkl
- Bc/Omit
- Dc/Omit
- Zonnon
- Pages with too many expensive parser function calls