Skip to content

Instantly share code, notes, and snippets.

@JoeStrout
Created January 11, 2024 15:59
Show Gist options
  • Save JoeStrout/f7f59dd7b97c56d2c55e59724f193300 to your computer and use it in GitHub Desktop.
Save JoeStrout/f7f59dd7b97c56d2c55e59724f193300 to your computer and use it in GitHub Desktop.
////
// Weird experiment to see what Rust-style traits might look like in MiniScript.
////
import "listUtil"
import "stringUtil"
PartialEq = {}
PartialEq.eq = function(other)
return refEquals(self, other)
end function
////
Display = {}
Display.fmt = function(f="", targetObj=null)
if targetObj == null then targetObj = self
if not f then return str(targetObj)
return f.fill(targetObj)
end function
////
Point = {}
Point.init = function(x, y)
self.x = x
self.y = y
return self
end function
Point.make = function(x, y)
return (new Point).init(x, y)
end function
////
// And now, to implement the PartialEq and Display traits on Point.
map.typeName = function()
value = self
if value.hasIndex("__isa") then value = value.__isa
// I'm using this loop in place of the index search, because the ordering of values and indexes is not determinant.
for kv in globals
if kv.key.startsWith("_") then continue
if refEquals(kv.value, value) then return kv.key
end for
return "unknown"
end function
map.implement = function(type)
for kv in type
if kv.key[0] != "_" then self[kv.key] = @kv.value
end for
// `_implements`, not `__implements`, as the double-underscore is reserved for the system.
if not self.hasIndex("_implements") then
self._implements = []
end if
self._implements.push type
end function
map.implements = function(type)
if self isa type then
return true
end if
if self.hasIndex("_implements") and self._implements.contains(type) then
return true
end if
// I'm keeping this duck-typing loop as a fallback. For now.
for k in type.indexes()
if not self.__isa.indexes.contains(k) then
return false
end if
end for
return true
end function
// Actually, if you do some smarty-smart things with the `globals`, reassigning the original type is no longer required.
Point.implement PartialEq
// Example of overriding default trait behavior.
// `impl Display for Point`
Point.fmt = function(f="")
if not f then f = "({x}, {y})"
return Display.fmt(f, self)
end function
p = Point.make(10, 12)
// Note how `p isa Point` is true, but `p isa Display` is false.
print "Built-in type-check:"
print "Is Point? {0}".fill([ p isa Point ])
print "Is Display? {0}".fill([ p isa Display ])
print "Is PartialEq? {0}".fill([ p isa PartialEq ])
print "====="
// But we can use `implements` to check for both kinds of izzyness.
print "With `implements`:"
print "Is Point? {0}".fill([ p.implements(Point) ])
print "Is Display? {0}".fill([ p.implements(Display) ])
print "Is PartialEq? {0}".fill([ p.implements(PartialEq) ])
print "====="
// And when we call p.fmt, we get the custom one.
print p.fmt("x={x}, y={y}")
print p.fmt // The overridden Display for Point will allow this to be rendered properly.
print p.fmt("({x}, {y})")
print "====="
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment