I am translating my go code into nim, which looks a bit messy compared to go.
It's clearer to put the current class object before the name, proc (this: MyType) named (arg1: int). Why are class objects and parameters written in the same brackets in NIM?
nim:
...
#editor
import xmltree
import strutils
type TabWidget = distinct pointer
proc tabName(this: TabWidget): string =
$input.tabwidget_tabName(cast[pointer](this))
proc docWindowManager(this: TabWidget): EditorWindow =
var dwPointer = input.tabwidget_dockWindowManager(cast[pointer](this))
if (dwPointer == nil):
return nil
return cast[ptr EditorWindow](dwPointer)[]
type TabsWidget = distinct pointer
proc init(this: TabsWidget, tabsWidgetInfo: XmlNode) = discard
proc info(this: TabsWidget): XmlNode = discard
proc tabCount(this: TabsWidget): int32 =
input.tabswidget_tabCount(cast[pointer](this))
proc tab(this: TabsWidget, index: int32): TabWidget =
cast[TabWidget](input.tabswidget_tab(cast[pointer](this), index))
type
JboxLayoutOrientation {.pure.} = enum
none
horizontal
vertical
type JboxLayout = distinct pointer
# proc info(): jboxInfo: XmlNode =
proc latticeContent(this: JboxLayout, index: int32): pointer =
input.jboxlayout_latticeContent(cast[pointer](this), index)
proc init(this: JboxLayout, jblInfo: XmlNode) =
input.widget_show(cast[pointer](this))
let jblState = jblInfo.attr("orientation")
case jblState:
of "n":
input.jboxlayout_setOrientation(cast[pointer](this), cast[int32](JboxLayoutOrientation.none))
of "h":
input.jboxlayout_setOrientation(cast[pointer](this), cast[int32](JboxLayoutOrientation.horizontal))
of "v":
input.jboxlayout_setOrientation(cast[pointer](this), cast[int32](JboxLayoutOrientation.vertical))
else:
raiseAssert "jblInfo failed orientation not n h v"
for latticeNode in jblInfo:
let offsetPer = latticeNode.attr("offsetPer")
let latticeIndex = input.jbox_layoutNewLattice(cast[pointer](this), parseFloat(offsetPer))
# if latticeNode.tag == "tabsWidget":
# else if atticeNode.tag == "layout":
type Jbox = distinct pointer
proc show(this: Jbox) =
input.widget_show(cast[pointer](this))
proc resize(this: Jbox, width, height: int32) =
input.widget_resize(cast[pointer](this), width, height)
proc centered(this: Jbox) =
input.jbox_centered(cast[pointer](this))
proc init(this: Jbox, jboxInfo: XmlNode) =
var jboxWidth = jboxInfo.attr("width")
var jboxHeight = jboxInfo.attr("height")
this.resize(cast[int32](parseInt(jboxWidth)), cast[int32](parseInt(jboxHeight)))
this.show()
var jblNode = jboxInfo.child("layout")
var jbl = cast[JboxLayout](input.jbox_jboxLayout(cast[pointer](this)))
jbl.init(jblNode)
proc newJbox() =
var jbox = Jbox(input.new_jbox())
...
golang:
...
type jBoxLayout uintptr
func (this jBoxLayout) init(jblEle *dom4g.Element) {
_editor.WidgetShow(unsafe.Pointer(this))
jblState, ok := jblEle.AttrValue("orientation")
if !ok {
}
switch jblState {
case "n":
_editor.JBoxLayoutSetOrientation(unsafe.Pointer(this), int(jboxLayoutOrientation_none))
case "h":
_editor.JBoxLayoutSetOrientation(unsafe.Pointer(this), int(jboxLayoutOrientation_horizontal))
case "v":
_editor.JBoxLayoutSetOrientation(unsafe.Pointer(this), int(jboxLayoutOrientation_vertical))
}
latticesEle := jblEle.AllNodes()
for _, latticeEle := range latticesEle {
if latticeEle.Name() != "layout" &&
latticeEle.Name() != "tabsWidget" {
return
}
offsetStr, ok := latticeEle.AttrValue("offsetPer")
if !ok {
offsetStr = "0"
}
offsetPer64, err := strconv.ParseFloat(offsetStr, 32)
if err != nil {
panic(err)
}
offsetPer32 := float32(offsetPer64)
latticeIndex := _editor.JBoxLayoutNewLattice(unsafe.Pointer(this), offsetPer32)
if latticeEle.Name() == "tabsWidget" {
tsw := tabsWidget(_editor.NewTabsWidget())
_editor.JBoxLayoutSetLatticeContent(unsafe.Pointer(this), latticeIndex, int(latticeType_tabsWidget), unsafe.Pointer(tsw))
tsw.init(latticeEle)
} else if latticeEle.Name() == "layout" {
jbl := jBoxLayout(_editor.NewJBoxLayout())
_editor.JBoxLayoutSetLatticeContent(unsafe.Pointer(this), latticeIndex, int(latticeType_layout), unsafe.Pointer(jbl))
jbl.init(latticeEle)
}
}
}
func (this jBoxLayout) info() *dom4g.Element {
jsonStr := _editor.JBoxLayoutJson(unsafe.Pointer(this))
var jblj jBoxLayoutJson
err := json.Unmarshal([]byte(jsonStr), &jblj)
if err != nil {
panic(err)
}
jblEle := dom4g.NewElement("layout", "")
switch jblj.State {
case "n":
jblEle.AddAttr("orientation", "n")
case "h":
jblEle.AddAttr("orientation", "h")
case "v":
jblEle.AddAttr("orientation", "v")
}
fmt.Println(jsonStr)
for i, latticeJson := range jblj.Lattices {
var latticeEle *dom4g.Element
if latticeJson.Type == "tabsWidget" {
tsw := tabsWidget(this.latticeContent(i))
fmt.Println(tsw)
latticeEle = tsw.info()
if latticeJson.OffsetPer != "" {
latticeEle.AddAttr("offsetPer", latticeJson.OffsetPer)
}
} else { // layout
jbl := jBoxLayout(this.latticeContent(i))
latticeEle = jbl.info()
if latticeJson.OffsetPer != "" {
latticeEle.AddAttr("offsetPer", latticeJson.OffsetPer)
}
}
jblEle.AddNode(latticeEle)
}
return jblEle
}
func (this jBoxLayout) newLattice() {
}
func (this jBoxLayout) setLattice() {
}
func (this jBoxLayout) latticeContent(index int) unsafe.Pointer {
return _editor.JBoxLayoutLatticeContent(unsafe.Pointer(this), index)
}
func (this jBoxLayout) LatticeCount() {
}
type tabsWidget uintptr
func (this tabsWidget) init(tabsWidgetInfo *dom4g.Element) {
tws := tabsWidgetInfo.Nodes("t")
for _, tw := range tws {
twName, ok := tw.AttrValue("name")
if !ok {
panic("")
}
if twName != "" {
twFt, ok := dockWindowManagers[twName]
if !ok {
_editor.TabsWidgetAddTab(unsafe.Pointer(this), "Not "+twName, nil, nil)
return
}
twV := reflect.New(twFt).Interface().(dockWindowManager)
twContent := twV.init(twName)
_editor.TabsWidgetAddTab(unsafe.Pointer(this), twName, twContent.parentPoint(), unsafe.Pointer(&twV))
twV.Init(nil)
} else {
_editor.TabsWidgetAddTab(unsafe.Pointer(this), "", nil, nil)
}
}
}
func (this tabsWidget) info() *dom4g.Element {
tabsInfo := dom4g.NewElement("tabsWidget", "")
for i := 0; i < this.tabCount(); i++ {
tw := this.tab(i)
tabInfo := dom4g.NewElement("t", "")
tabInfo.AddAttr("name", tw.tabName())
tabsInfo.AddNode(tabInfo)
dw := tw.docWindowManager()
fmt.Println(dw)
if dw != nil {
dw.Serialize()
}
}
return tabsInfo
}
func (this tabsWidget) tabCount() int {
return _editor.TabsWidgetTabCount(unsafe.Pointer(this))
}
func (this tabsWidget) tab(index int) tabWidget {
return tabWidget(_editor.TabsWidgetTab(unsafe.Pointer(this), index))
}
...
Because procedures are not associated with "class" objects. You can have
type
T0 = object
T1 = object
T = object
O = object
converter toT(this:any):T = discard
proc p(this:T0):O = discard
proc p(this:T0, that:T1):O = discard
proc p(that:T1, this:T0):O = discard
proc p(this:T0, that:T1, rest:varargs[T, toT]):O = discard
converter (this: any) toT (): T = discard proc (this: T0) p (): O = discard proc (this: T0) p (that:T1): O = discard proc (this: T0) p (that:T1, rest:varargs[T, toT]): O = discard proc (that :T1) p (this:T0): O = discard
Cann't nim be designed this way? I just started learning this language.
Nim main paradigm is structured programming, just like C. Meaning everything is a free-standing procedure.
Assuming Nim was OOP-first we could have chosen the Python/C++ approach where "this"/"self" is completely implicit and you don't even see it declared or typed. Or sink into the Java approach and not allow free-standing procedures and force you to always create Managers, Executors, Handlers, Services to handhold your routines.
Yes, I use multiple operating systems, I am fed up with the free-standing procedure of the c language, but I have to do this (although I can also write oop-like code, but it is a chicken rib in c). but in nim can reflect oop-like, such as the existence of inheritance.
But for a lot of reasons, it will lead to messy writing. (Although it can be solved with macros, I don't like to do this outside of DLS)
Although nim has a lot of flaws but doesn't prevent it from becoming a powerful language, that's why I'm trying to write some code from nim, for example, golang doesn't support dlclose.
I have just gotten into contact with this language and there is still a lot to learn.