Good looking definition?
BlitzMax Forums/BlitzMax Beginners Area/Good looking definition?
| ||
So I really want to define something with style in BMax but I´m failing miserable. With primitive types you may say something like: Local name:int = 1 I would like to define new types with methods and functions and be able to define them like so: Local name:sometype = someparameter So far I 've only succeeded with this: Local name:sometype = New sometype ; name = sometype.Create(someparameter) As you can see It gets very ugly (too verbose and repetive. e.g. nonmeanful words like New And Create, and type is said 3 times instead of 1, the name is said 2 times instead of 1. Are there any OO wizardry that could explain this problem from a nice angle how to do this? I would like to be able to create something similiar to this: ' Create Local name:owntype = parametershere ' < the idea I´m striving for (something according to those lines) ' ... and Use (using works fine already) name.strawberryfield = 100 name.add(10,20,"plus") |
| ||
Bmax doesn't work that way. |
| ||
Function CreateMyObj:myobj(param:int) Local o:myobj = new myobj o.strawberryfield = param Return o End Function Local myO:myobj = CreateMyObj(15) Bye Ron |
| ||
Hi, alternatively you can hide the function inside your type: Local ts:Tsome = Tsome.Create(12, 20) ts.ShowAll() Type Tsome Field x:Int, y:Int Function Create:Tsome(x:Int, y:Int) Local ts:Tsome = New Tsome ts.x = x ts.y = y Return ts EndFunction Method ShowAll() Print x + " | " + y EndMethod EndType -Henri |
| ||
And alternatively, for better polymorphism, you can use a method :Local ts:Tsome = New Tsome.Create(12, 20) ts.ShowAll() Type Tsome Field x:Int, y:Int Method Create:Tsome(x:Int, y:Int) Self.x = x Self.y = y Return Self End Method Method ShowAll() Print x + " | " + y EndMethod EndType which facilitates subclass instantiation. |
| ||
@Derron Thanks, that worked If I changed it and added a type before the create function. like so Local name:type = type.create(parameters) That's my best shot so far, any other ideas? Still there are clones of the type, there's the keyword create (or any other keyword I name it but I seem to need a keyword) Are there no Constructors available to get away with create? Or similiar? |
| ||
Now Casaber, don't forget, you can just make everything strings and sort it out from there in future code. "@fruit=nnnn" where the "@" in the front defined the variable TYPE, whichever you want to build and interpret, then stuff the value after the equals. Make that an array if you so choose. I've done this many times to create unique variable types. |
| ||
@Henri Thanks, that gives the exact same creation syntax as Derron. It seemed that my code already was able to do that I discovered I just did not knew about that syntax. You also added inside it Local ts:Tsome = New Tsome I got lost there what that means. It defines a type of itself within itself? @Brucey that will add a "new" keyword, what kind of flexibility does that give in simple terms? |
| ||
@dw817 This is not strings though, I guess I explained abit poorly I tried my sleepy best. I´m trying to learn how Bmax does it's OO. Wanna see the mess? It's a bit hefty for most eyes I know I just need something up and running this evening hopefully. The important bit is the Create method, and the two top lines which are how everything will look when you actually use it. It should look good. It's for my Shader VBO. And I thought I'll try to code a proper library. So I wanted a nice interface you know? Local shader:TShader = New TShader ; shader=TShader.Create(VERTEX,PIXEL) ' Old way Local shader:Tshader = Tshader.Create(VERTEX,PIXEL) ' New way (best so far) Type TShader Field PO:Int Function Create:TShader(VC:String,PC:String) ; Local p:TShader = New TShader ; p.PO = glCreateProgramObjectARB() VS = glCreateShader(GL_VERTEX_SHADER) ; PS = glCreateShader(GL_FRAGMENT_SHADER) Local SC:Byte Ptr ; Local SL:Int SC = VC.ToCString() ; SL = VC.length ; glShaderSourceARB VS,1,Varptr SC,Varptr SL ; MemFree SC ; glCompileShaderARB VS SC = PC.ToCString() ; SL = PC.length ; glShaderSourceARB PS,1,Varptr SC,Varptr SL ; MemFree SC ; glCompileShaderARB PS glAttachObjectARB p.PO,VS ; glLinkProgramARB p.PO ; glAttachObjectARB p.PO,PS ; glLinkProgramARB p.PO ; glDeleteObjectARB VS ; glDeleteObjectARB PS Return p End Function Method bind() ; glUseProgramObjectARB PO ; End Method Method unbind() ; glUseProgramObjectARB 0 ; End Method Method UI1(name:String,v:Int) ; Local SC:Byte Ptr = name.ToCString() ; Local l:Int = glGetUniformLocationARB(PO,SC) ; glUniform1iARB l,v ; MemFree SC ; End Method Method UF1(name:String,v:Float) ; Local SC:Byte Ptr = name.ToCString() ; Local l:Int = glGetUniformLocationARB(PO,SC) ; glUniform1fARB l,v ; MemFree SC ; End Method Method UF2(name:String,v1:Float,v2:Float) ; Local SC:Byte Ptr = name.ToCString() ; Local l:Int = glGetUniformLocationARB(PO,SC) ; glUniform2fARB l,v1,v2 ; MemFree SC ; End Method End Type |
| ||
Nono Casaber. Strings can carry, well, just about anything ! Remember when we talked about using "#" as the first character in a string to let you know it was a number ? This is quite similar. You look for an "@" as the first character to a string, and that tells you what KIND of variable you want to make it. Then get the data after the "=" sign, and you're all set ! global vartyp$[5] vartyp$[0]="@box=1,2,3,4" vartyp$[1]="@triangle=1,2,3" vartyp$[2]="@desc=For more information press [F1]" vartyp$[3]="#863474" vartyp$[4]="Frederick"See ? It's easy ! :) @box expects to have 4 comma delimited numbers @triangle expects 3 of them @desc is a special variable you can set and have appear anywhere (object-oriented) # is of course just a number that you can add, subtract to, or what have you and the last is not denoted as special, so - it's just treated as a normal string. |
| ||
My code is of course _not_ what I would suggest to do, but created the "shortest" part after the "=". Each "Type" has an inbuilt method named "new", this is calles as soon as you create an instance of a type. If you do a "mytype = new TMyType" then a new instance of "TMyType" is created, and the "new()" method is called. In Blitzmax it is not possible to adjust the "new()" to accept parameters. Difference between "Function Create:TMyObject(params...)" and "Method Create:TMyObject(params...)" is, that the Method can only be called by an already existing instance - this is why Brucey did a "new TSome.Create(...)". A Function is callable by the type but therefore needs to create an instance on its own (this is what Henri posted). Other differences? I cannot come up with some, so I think there are none. Small hint: While BlitzMax does not allow overloading, so you cannot do the following: Method Create:TMyObject(param:int)... Method Create:TMyObject(param:int, param2:string)... But what you are able to do is, to override the returned object type (in extended types). SuperStrict Type TTypeA Field a:int Method Init:TTypeA(param:int) a = param return self End Method Method SetA:TTypeA(param:int) a = param return self End Method End Type Type TTypeB extends TTypeA Field b:int Method Init:TTypeB(param:int) Super.Init(param * 4) 'this delegates some work to TTypeA b = param * 2 return self End Method 'override to allow chaining Method SetA:TTypeB(param:int) Super.SetA(param * 4) return self End Method Method SetB:TTypeB(param:int) b = param return self End Method End Type local myA:TMyTypeA = new TMyTypeA.Init(5).SetA(10) local myB:TMyTypeB = new TMyTypeB.Init(5).SetA(10).SetB(5) bye Ron |
| ||
@dw817 I think I will try use that somehow somewhere maybe even in this code but here my problem is that BMax has verbose syntax. It seem that I need to do this: Local shader:Tshader = Tshader.Create("Depresso") When I would like to be able to do this: Local shader:Tshader("all I need is a cup of Coffee") |
| ||
You can create your own mini-programming language or interpreter if you want, Casaber. Many times in big code I've written, I encapsulate an interpreter to make up for what the programming language cannot do. Let's see ... I really don't know anything about that shader definition, but I know you can do this. Local shader:TShader,var$ var$="@ts:tshader=all I need is a cup of coffee" If Left$(svar$,3)="@ts" Then shader=tshader.Create(Mid$(svar$,Instr(svar$,"=")+1))That may not be a perfect example, but I think you can see how to work this in. . . . Will be gone for a few hours, BBL. |
| ||
@Derron That was a bumpy ride, Okay'l think I will have to take it slow. I´m okayish with this new syntax I got now. I think I'll keep it on this level for while now. |
| ||
I just want to fill you in quickly what I ended up that evening becuase I thought it was, but a very powerful sugar hack. At times when you really want it. And now i did. Here it is: Okay the goal was to find something easy on the eyes for own types, similiar to inbuiilt primitivetypes such aa ' Local number:int = 0 This was my 1st attempt: Local shader:TShader = New TShader ; shader=TShader.Create(VERTEX,PIXEL) Which could be simplified into this: Local shader:Tshader = Tshader.Create(VERTEX,PIXEL) But then I got the idea to add this line in the code Function CreateTShader:TShader(VC:String,PC:String) ; Return TShader.Create(VC,PC) ; End Function Now I'm able to use this final version: Local shader:Tshader = CreateTShader(VERTEX,PIXEL) I guess I's also a way to overload inbuilt Bmax commands into own Types aswell. I´m not saying it's a good hack if you use OO in all kinds of way - but it might. |
| ||
But then I got the idea to add this line in the code... Which is basically what Derron posted in #3. btw, I don't think your code examples are at all user-friendly or readable. Having as many statements as possible on a single line (separated by semi-colons) is neither clear nor easily maintainable. |
| ||
I only code because I find it fun, and the style that you see goes along with that fun. It's actually very maintainable for the right eyes, even if it's not "mainstream". I''m basically offering you to see something very personal when I show any code. I don´t have the strength right now to convert back and forth between "mainstream" and my own. Hope I won´t be neeeding to here that kind of critics in the future on the style becuase you're gonna see plenty of it. If that's not okay I will not use this forum. |
| ||
Even if you do not go d'accord with it - I have to support Brucey's argument.Function CreateTShader:TShader(VC:String,PC:String) ; Return TShader.Create(VC,PC) ; End Function Is not very readable. Imagine you add 2 other options Function CreateMyObject:TMyObject(a:string,b:TMySimpleType,c:TAnotherType=null,d:int var) ; Return TMyObject.Create(a,b,c,d); End Function While it saves on "lines of code"-count, you will more likely miss things in so long lines. This is the reason, many editors have this vertical line at about 72 characters. It stresses the eyes if you have to read long lines. I try to avoid long lines if possible, especially if there is no need (";" forcefully puts things on one line). Only real exceptions for me, are longer formulas (or parts just being 3-4 chars longer than the "virtual limit"). This is because Blitzmax needs those ".." to connect multiple lines belonging together - which makes manual formatting less easier then automatic recognition (brackets, or "then" - or recognition of "or" or "and")... ... so in your example, I would not "multi-line" a big function header just because of so many params, but the "type.Create(a,b..)" would be done on another line, same for "End Function". As long as you keep the code for yourself long lines might be something like a "personal taste", but when working with teams (or publishing your code) it is a good idea to try to follow a certain "guideline". So nobody "forbids" to use the style you like, they (Brucey and Myself in this case) just give hints / personal thoughts on what you posted. @CreateTShader() For me such helper functions are known in BlitzMax to add "convenience" for non-oop-coders. There is "LoadStream()" which calls "stream.load()", "LoadImage()" which calls "image.Load()" ... and other things. Nonetheless I also would like to see custom "New()" methods (local shader:TShader = new TShader(param,param2)) but we did not get it with vanilla, so we wont see it added there (backwards compatibility?). A "local shader := TShader(bla)" would be nice too (auto type setting - like it is allowed in Monkey). But hey, it works well without these convenience functions and you code things once instead of retyping it for every execution. BTW: Local shader:TShader = New TShader ; shader=TShader.Create(VERTEX,PIXEL) could be done as Local shader:TShader = New TShader.Create(VERTEX,PIXEL) (the Create() is then a method, returning "self", this is what Brucey described in #5) At the end it is all a matter of taste - and once you publish your taste, other cooks will come and drop a line about that :-) bye Ron |
| ||
Not to bite the already bit butt but I did mention this one earlier time, Casaber. I only use ";" to define values if they'll fit within the first 50-characters, in fact I try very hard not to have any single line greater than 50-characters if at all possible. a=deskrect[0] ; b=deskrect[1] ; c=deskrect[2] ; d=deskrect[3] which for me is pretty extreme. Also If grid ' operate on grid ? x=bound(x,4,maxx) ; y=bound(y,4,maxy) ' it's all on a tight h=h/4*4 ; v=v/4*4 ; x=x/4*4 ; y=y/4*4 ' grid endif But as you can see once again these are just like-minded variables being set so it's not too hard to follow, and you don't have to scroll the page to see any of the commands or functions. No, it's when you mix actual BlitzMAX commands on a single line does it get a little obfuscated. Function erasepixels(img:Timage,h,v,x,y) ; local i,j,p:tpixmap ; for i=0 until y ; for j=0 until x ; writepixel p,h+j,v+i,0 ; next ; next ; endfunction This does bring up an interesting point. GFA had the ability of 'folding' functions. That is, I could press [F11] at the beginning of a function I created and it would change it to: Function erasepixels(img:Timage,h,v,x,y) and not show the contents of the function until I pressed [F11] again, keeping your source code easy to read, especially when you were satisfied with the contents of any of your functions. Perhaps, Casaber, this is what you want to keep your coding readable ? Guys, is this ability available in MaxIDE ? |