• Subject: More functional thoughts (Was: vectors and Lua)
• From: RLake@...
• Date: Mon, 30 Jun 2003 12:04:50 -0500

```Mark Hamburg escribió:

> One problem with this approach is that it is less "natural" than the
value
> semantics version. For example, a lot more people would probably be
> comfortable writing:

>    position.x = PinToGrid( position.x )

> Than writing:

>    position = postion:setX( PinToGrid( position.x ) )

> Even without the direct assignment, you'd probably get lots of people
> writing and then debugging:

>     position:setX( PinToGrid( position.x ) )

Wouldn't it be more natural to write the following?

pinned = PinXtoGrid(position)

This is basically the same semantics issue as you have with gsub. If
you're used to mutable strings, you are perhaps tempted to write:

string.gsub(name, "%l", string.upper)

name = string.gsub(name, "%l", string.upper)

but I haven't seen much chatter about that on this list, so I assume that
it is not much of a problem.

By analogy, I suppose the primitive could be:

pinned = vector.vsub(position, "@x", vector.PinToGrid)

or some such.

Actually, that could be cool:

pinned = vector.vsub(position, ".", vector.PinToGrid)

------ Re: temporary objects

It is certainly the case that temporary objects mount up. One solution can
be found in the functional implementation of tuples, using functional
composition to avoid creating temporary objects.

ej: (as before)
function vector(_x, _y, _z) return function(fn) return fn(_x, _y, _z)
end end
-- and now:
function vunpack(_x, _y, _z) return _x, _y, _z end

function scaleBy(q)
return function(_x, _y, _z) return q * _x, q * _y, q * _z end
end

function subtractPoint(v)
local x, y, z = v(vunpack)
return function(_x, _y, _z) return _x - x, _y - y, _z - z end
end

local x, y, z = v(vunpack)
return function(_x, _y, _z) return _x + x, _y + y, _z + z end
end

function rotateBy(theta)
local sintheta, costheta = math.sin(theta), math.cos(theta)
return function(_x, _y, _z)
return _x * costheta - _y * sintheta, _x * sintheta + _y * costheta,
_z
end
end

-- from which we can compose:
function transform(centre, expand, theta)
local a, r, sc, s = addPoint(centre), rotateBy(theta),
scaleBy(expand), subtractPoint(centre)
return function(_x, _y, _z) return a(r(sc(s(_x, _y, _z)))) end
end

> centre = vector(2, 2, 2)
> point = vector(3, 3, 7)
> xform = transform(centre, 2, math.pi / 4)
> =point(xform)
2       4.8284271247462 12
> =gcinfo()
32      38
> for i = 1, 100000 do point(xform) end
> =gcinfo()
33      38

I accept that it takes a while to get the hang of this sort of thing.

With an explict compose operator, the syntax is a lot cleaner: