Chapter 6: Fake objects and structs (arrays)

6.1. Using an array as a context struct

Using the passed-by-reference nature of arrays, it is possible to use an array to represent a data structure (similar to a C struct passed by pointer) that is passed to functions that manipulate it:
example program ch6_ex1
rem calculate the overall intensity of the color
function color_update(CLR)
	CLR["intensity"] = (CLR["red"]/255 + CLR["green"]/255 + CLR["blue"]/255)/3
end function

CLR1["red"] = 15
CLR1["green"] = 200
CLR1["blue"] = 60

color_update(CLR1)

fawk_print(CLR1["intensity"])

This helps implementing data driven programming:

6.2. The "struct syntax" of array indexing

To ease using the above pattern, fawk implements the "." operator that is a shorthand syntax for an array indexing with the string version of the field name. The following two array references are equivalent:

arrname.fieldname
arrname["fieldname"]

Using this syntax the above example cn be rewritten into a more readable form:
example program ch6_ex2
rem calculate the overall intensity of the color
function color_update(CLR)
	CLR["intensity"] = (CLR.red/255 + CLR.green/255 + CLR.blue/255)/3
end function

CLR1.red = 15
CLR1.green = 200
CLR1.blue = 60

color_update(CLR1)

fawk_print(CLR1.intensity)

6.3. Using an array as an object

The next logical step is to bundle the functions that can manipulate the data, to the same array. This is possible since function references can be saved in variables or in array members (see section 4.6.):
example program ch6_ex3
rem load a color array with component values
function color_load(CLR, r, g, b)
	CLR.red = r
	CLR.green = g
	CLR.blue = b
end function

rem calculate the overall intensity of the color
function color_update(CLR)
	CLR["intensity"] = (CLR.red/255 + CLR.green/255 + CLR.blue/255)/3
end function

rem initialize the object
CLR1.update = color_update
CLR1.load = color_load

rem load and update
CLR1.load(CLR1, 15, 200, 60)
CLR1.update(CLR1)

fawk_print(CLR1.intensity)

6.4. Inheritance: "base class"

It is possible to set up a "base class" for the color structure so that different object instances can be created more easily:
example program ch6_ex4
rem  load a color array with component values
function color_load(CLR, r, g, b)
	CLR.red = r
	CLR.green = g
	CLR.blue = b
end function

rem  calculate the overall intensity of the color
function color_update(CLR)
	CLR["intensity"] = (CLR.red/255 + CLR.green/255 + CLR.blue/255)/3
end function

rem initialize the "base class"
COLOR.update = color_update
COLOR.load = color_load

rem create an instance of COLOR called CLR1
for i in COLOR
	CLR1[i] = COLOR[i]
next i

rem load and update
CLR1.load(CLR1, 15, 200, 60)
CLR1.update(CLR1)

fawk_print(CLR1.intensity)

Obviously "multiple inheritance" can be implemented the same way, simply using two loops for copying fields from two different "base classes":
example program ch6_ex5
rem load a color array with component values
function color_load(CLR, r, g, b)
	CLR.red = r
	CLR.green = g
	CLR.blue = b
end function

rem calculate the overall intensity of the color
function color_update(CLR)
	CLR["intensity"] = (CLR.red/255 + CLR.green/255 + CLR.blue/255)/3
end function

rem convert a single digit to hex
function hexdigit(digit)
	hexdigit = "?"
	if digit < 10 then hexdigit = digit
	if digit = 10 then hexdigit = "A"
	if digit = 11 then hexdigit = "B"
	if digit = 12 then hexdigit = "C"
	if digit = 13 then hexdigit = "D"
	if digit = 14 then hexdigit = "E"
	if digit = 15 then hexdigit = "F"
end function

rem convert a byte value to a 2-digit hex string
function tohex2(val   ,d1,d2)
	d1 = int(val / 16)
	d2 = val mod 16
	tohex2 = hexdigit(d1) @ hexdigit(d2)
end function

rem convert the color to html color code
function html_print_color(CLR)
	html_print_color = "#" @ tohex2(CLR.red) @ tohex2(CLR.green) @ tohex2(CLR.blue)
end function

rem initialize the color "base class"
COLOR.update = color_update
COLOR.load = color_load

rem initialize the html "base class"
HTML.print_color = html_print_color

rem create an instance of COLOR+HMTL called CLR1
for i in COLOR
	CLR1[i] = COLOR[i]
next i
for i in HTML
	CLR1[i] = HTML[i]
next i

rem load and update
CLR1.load(CLR1, 15, 200, 60)

fawk_print(CLR1.print_color(CLR1))

6.5. Why it is not real OOP

There are many major features of OOP missing: there are no automatisms, everything needs to be done by the user, in code. Most notably there is no constructor or destructor and passing the object as the first argument is done manually, there is no "this" in functions.