leafo / moonscript

:crescent_moon: A language that compiles to Lua
https://moonscript.org
3.23k stars 191 forks source link

Any method to use if statement in class method define? #445

Closed zeroxer closed 1 year ago

zeroxer commented 1 year ago

class Person extends Thing if is_debug say_name: => print "Debug: Hello, I am #{@name}!" else say_name: => print "Release: Hello, I am #{@name}!"

transmutrix commented 1 year ago

Not leafo, but I assume the benefit you want is compile time evaluating that? AFAIK MoonScript doesn't do any compile-time evaluation of any kind. I would just do the check inside the method, personally.

A convention I use in several languages is to have a constant called Debug in each module and set it to true when I need debug output or extra checks turned on.

I dunno what your use case is, so I can't really speak to the effect on performance adding such ifs would have, but for the kind of things I tend to write, it is insignificant compared to other costs.

zeroxer commented 1 year ago

is_debug is just one case. I want to use this because I can share some function code out of if/else and use the same function name with a clean code style. I dont want to use so many if/else in function. That was annoying when you have global is_debug(or something else), and have a lot debug code (or something else) to use. If support this usage, we can just remove the functions just for is_debug and keep the other functions no change.

Thanks for your reply.

transmutrix commented 1 year ago

Ah, I see what you mean.

Actually, I think you can have almost exactly what you wanted. I tried this in the MoonScript playground here, and it does work:

class Person
  say_name: if is_debug
    => "debug"
  else
    => "release"

test = Person!
test\say_name!

It replaces the method definition based on the flag at require time, so should work I think. Here's the generated Lua:

local Person
do
  local _class_0
  local _base_0 = {
    say_name = (function()
      if is_debug then
        return function(self)
          return "debug"
        end
      else
        return function(self)
          return "release"
        end
      end
    end)()
  }
  _base_0.__index = _base_0
  _class_0 = setmetatable({
    __init = function() end,
    __base = _base_0,
    __name = "Person"
  }, {
    __index = _base_0,
    __call = function(cls, ...)
      local _self_0 = setmetatable({}, _base_0)
      cls.__init(_self_0, ...)
      return _self_0
    end
  })
  _base_0.__class = _class_0
  Person = _class_0
end
local test = Person()
return test:say_name()
zeroxer commented 1 year ago

Cool!

I have tried one as fellow. It seems the single line of => after if is_debug is a must. Is there any way to use if is_debug => like else => ?

is_debug = true

class Person
    say_name: if is_debug
      =>
        print "Debug: Hello, I am #{@name}!"
        print "Good Job"
    else =>
        print "Release: Hello, I am #{@name}!"
        print "Good Job"

    print_debug: if is_debug
      =>
        print "Print in debug"

with Person()
    .name = "MoonScript"
    \say_name!

with Person()
    .name = "DebugTest"
    \print_debug!