Compound data type: Difference between revisions
Content added Content deleted
Drkameleon (talk | contribs) |
(Added Quackery.) |
||
Line 1: | Line 1: | ||
{{task| |
{{task|rBasic language learning}} |
||
{{Data structure}} |
{{Data structure}} |
||
Line 1,884: | Line 1,884: | ||
>>></lang> |
>>></lang> |
||
=={{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. |
|||
===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. |
|||
<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</lang> |
|||
{{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. |
|||
<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</lang> |
|||
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> |
|||
<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 ) |
|||
</lang> |
|||
{{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: |
|||
<lang> [ witheach peek ] is {peek} ( { p --> x ) |
|||
[ dip dup |
|||
witheach [ peek dup ] |
|||
drop ] is unpack ( { p --> * ) |
|||
[ reverse |
|||
witheach |
|||
[ dip swap poke ] ] is repack ( * p --> { ) |
|||
[ dup dip |
|||
[ rot dip |
|||
[ unpack 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{ ( [ $ --> [ $ )</lang> |
|||
Finally we use <code>struct{</code> etc. to fulfil the requirements go the task. |
|||
<lang Quackery> struct{ x y }struct point |
|||
point |
|||
dup x {peek} echo cr |
|||
99 swap y {poke} |
|||
y {peek} echo cr</lang> |
|||
{{out}} |
|||
<pre>null |
|||
99 |
|||
</pre> |
|||
=={{header|R}}== |
=={{header|R}}== |