Jump to content

Compound data type: Difference between revisions

Added Quackery.
(Added Quackery.)
Line 1:
{{task|BasicrBasic language learning}}
{{Data structure}}
 
Line 1,884:
 
>>></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}}==
1,462

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.