This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Sewbacca's profile picture

Redirecting a class

Started by Sewbacca, 05 November 2016 - 11:04 PM
Sewbacca #1
Posted 06 November 2016 - 12:04 AM
Hey guys,

I have written a class and
all methods should to be called with a ':'.
If someone calls a method with a '.', then it should use the current stdoutput (like object.read() [io.read()] and object:read()).
Has someone any idea to do this?

P.S. In the first case is the method of an instance, in the second case is the method static.
Edited on 05 November 2016 - 11:13 PM
Lupus590 #2
Posted 06 November 2016 - 12:16 AM
I'm sure there is a metatable magic trick which can get self for a table even though you didn't pass it or use the colon. I'm having a look for it. Can't find it.
Edited on 05 November 2016 - 11:38 PM
H4X0RZ #3
Posted 06 November 2016 - 12:28 AM
I'm sure there is a metatable magic trick which can get self for a table. I'm having a look for it.

__index has two arguments. The table you are trying to access and the key.

If you have an __index like this it should allow you to access functions without using :


__index = function(t,k)
  if(type(rawget(t,k)) == "function") then
	return function(...) return rawget(t,k)(t,...) end
  end
end
Edited on 06 November 2016 - 12:10 PM
KingofGamesYami #4
Posted 06 November 2016 - 02:46 AM
I believe Lupus was looking for something along the lines of this:


__index = function( t, k ) --# the metatable function
  local value = rawget( t, k ) --# bypass it to get the actual value
  if type( value ) == "function" then --# if it is a function
    return function( ... ) --# wrap it in another function which...
      if ... == t then --# checks if the first argument is the table
         --# if it is, it was called with :
      else
         --# otherwise, it was called with a .
      end
    end
  end
  return value
end

Note: This is a filthy, untested* hack and should probably be avoided. It also can't tell the difference between a:b() and b( a ), because they are the same.

*I'm writing this from memory.
Sewbacca #5
Posted 06 November 2016 - 10:48 PM
Thanks, but function in __index decreases the speed. Do anyone knows an other solution?
I just want to achieve that if sb. calls object.method instead of object:method, the object get as the first argument the static class.
Edited on 06 November 2016 - 09:48 PM
KingofGamesYami #6
Posted 06 November 2016 - 11:11 PM
object:method() is identical to object.method( object ). You could define the method like this:


object.method( self, thing )
  if self == object then
    print( "Maybe called using :" )
  else
    print( "Called using ." )
  end
end
H4X0RZ #7
Posted 07 November 2016 - 05:29 AM
object:method() is identical to object.method( object ). You could define the method like this:


object.method( self, thing )
  if self == object then
    print( "Maybe called using :" )
  else
    print( "Called using ." )
  end
end

But aren't you bound to one instance of the class then?

Thanks, but function in __index decreases the speed. Do anyone knows an other solution?
I just want to achieve that if sb. calls object.method instead of object:method, the object get as the first argument the static class.

Sure. It's "slower". But the speed decrease likely is so small that you won't even notice. Sometimes you just have to decide between speed and convenience.
Edited on 07 November 2016 - 04:35 AM
Sewbacca #8
Posted 07 November 2016 - 12:40 PM
object:method() is identical to object.method( object ). You could define the method like this:


object.method( self, thing )
  if self == object then
	print( "Maybe called using :" )
  else
	print( "Called using ." )
  end
end
I wanna check out the difference between object.method and object:method (or object.method(object) (I knew that the ':' opperator just hides the self argument)). If self is given, then it works with the instance. If not, then use the static class (you know what i mean).