a bad practice?
Blitz3D Forums/Blitz3D Programming/a bad practice?
| ||
Referred to as a bad programming practice to use functions such as GOTO or GOSUB, perhaps not part of the language and are good for something, my concern is that without GOTO I see no other possible way to do little or nothing I've done . Greetings. |
| ||
You can write a program only with GOTO, PEEK and POKE. Then you can translate it almost command for command directly to Assembler. Just don't expect to get a Job as a programmer when you release Surcecodes with GOTO. Personally I often use it to skip parts of the code (a kind of block remark). An other situation where GOTO makes sense is a multiple nested FOR loop that you want to exit. Using EXIT would exit only from one For loop, but with Goto you can exit to a label right after the whole nested structure. Using too much GOTO will result in socalled "Spaghetti-Code", that is hard to analyze and to edit and to debug. GOSUB is obsolete IMHO because you can use a FUNCTION instead and that's even good practice. It's also good practice to declare all local variables in a Function explicitely as LOCALs, for in case of globals with the same name. |
| ||
Give us an example of where you have used goto or gosub and we can show you a better function derived solution to your code. |
| ||
Shambler Hi, well I'm glad your disposal to help me understand better. What I've done so far is not much, is simply a menu of a game where you have options to change the screen resolution, the quality of the shadows and into a level and return to the main menu, you see this I have made with the Goto command. ;======================================================== ; Proyecto : Beta ; Nombre File : Menu_Principal.bb ; Programador : Yue Rexie ; Empresa : Iris3D -Games Studios- © ; URL : http://www.iris3d.tk ; © : 2007-2011 ;======================================================== ; OBJETIVO : Menu Principal ;======================================================== .Menu_Inicial ;----------------------------- ; Fisica Implementada. ;----------------------------- pxCreateWorld(0,"t>4a3624l]64dm60]m28d\48mm70UT28") pxSetGravity (0,-30,0) ;Menu = 1 MoveMouse GraphicsHeight()/2+100,GraphicsHeight()/2 CambiandoR = False ;----------------------------- ; Includes Especiales -S- ;----------------------------- Include "Includes3\ShadowsSimple.bb" .Cambiando_Sombra CreateShadow Calidad ;ShadowRange 1 Global Textura0 = ShadowTexture() ;----------------------------- ; Includes Recursos2 ;----------------------------- Include "Includes\Recursos2.bb" ;----------------------------- ; Escena del Menu. ;----------------------------- Crear_Menu() CreateShadowCaster Jeep,0,1 CreateShadowCaster Llanta0,0,1 CreateShadowCaster Llanta1,0,1 CreateShadowCaster Llanta2,0,1 CreateShadowCaster Llanta3,0,1 EntityTexture Casa,Textura0,0,1 ;----------------------------- ; Emisor Particulas. ;----------------------------- Type Particle_Star Field particle Field sprite End Type Global EmisorP = pxParticleCreateEmitter() pxParticleEmitSetRadius(EmisorP, .2) pxParticleEmitSetStartSpeed( EmisorP, 0,.2) pxParticleEmitSetTDAcceleration(EmisorP, -1, 2, 0) pxParticleEmitSetRandRadius( EmisorP, .1) pxParticleEmitSetScaleFactor(EmisorP, 1, 0.1) pxParticleEmitSetPosition (EmisorP,-1.7,4.55,6.75) Repeat n=1-n If n=1 CreateParticleStar() ;PointEntity Camara,Jeep ;CamaraFalsa() If KeyDown(200) MoveEntity Camara,0,0,-.2 If Calidad <> -1 UpdateShadows Camara,1.0 If Calidad = -1 FreeShadows() AntiAlias AAlias UpdateParticleStar() pxRenderPhysic(60,0) pxParticleUpdateEmitter(EmisorP) RenderWorld 1.0 ; Funciones ;DebugShadow Menu() Text_(0,0,FPS()+ "Memoria Usada : " +StarAmount + " " + Menu,100,100,0) Flip Turbo If CambiandoR = True StarAmount = 0 Delete Each Particle_Star Goto Cambio_Resolucion End If If CambiandoS = True Eliminar_Menu() FreeShadows() StarAmount = 0 Delete Each Particle_Star ClearWorld True,True,False CambiandoS = False Goto Cambiando_Sombra End If If Nivel = 1 Eliminar_Menu() FreeShadows() Delete Each Particle_Star StarAmount = 0 ClearWorld True,True,False Goto Cargando End If Forever .Cargando ;----------------------------- ; Cargando Nivel 1 ;----------------------------- Include "Includes\Recursos3.bb" Camara = CreateCamera() Repeat Local Frames# Local Iniciando_Nivel# Frames = Frames + .5 If Frames => 13 Iniciando_Nivel = Iniciando_Nivel +.5 Frames = 0 If Iniciando_Nivel > .5 Iniciando_Nivel = 0 Goto Primer_Nivel End If End If RenderWorld StartDraw ; If Frames > 0 And Frames < 4 ; SetColor 255,0,0 ; ElseIf Frames >4 And Frames < 8 ; SetColor 255,255,0 ; ElseIf Frames > 8 And Frames < 13 ; SetColor 0,255,0 ; End If DrawImageEx (Cargando,GraphicsWidth()/2,GraphicsHeight()/2,Frames) EndDraw Text 0,0, "Memoria Disponeble :" + AvailVidMem() Flip Turbo Forever .Primer_Nivel ClearWorld True,True,False Include "Includes\Nivel_1.bb" For example to change the quality of the shadow use this. If CambiandoS = True Eliminar_Menu() FreeShadows() StarAmount = 0 Delete Each Particle_Star ClearWorld True,True,False CambiandoS = False Goto Cambiando_Sombra End If CambiandoS is a variable that indicates that a new quality value was assigned to the quality of the shade, so I use the goto to remove the entire scene and reconstruct the new quality of the shadow. |
| ||
Tobe honest i am not even sure why b3d has goto and gosub. They are largely useless and should not ever be used. There should be no situation where one is needed (except some very rare circumstances), where a well structured switch (select), if-tree or loop break can do the job much better. Basically if you need to use goto's the code is not structured properly. ps you should never use repeat --- forever s either ALWAYS condition them. Last edited 2010 |
| ||
you should never use repeat --- forever s either ALWAYS condition them Not necessarily: http://en.wikipedia.org/wiki/Control_flow#Loop_with_test_in_the_middle That is to say, yes there is a condition check (implemented via "If cond Then Exit") but it's not on the "Until" clause; in that case, having an "Until" there anyway would make such code less clear. I would recommend doing some reading up on Structured Programming, and possibly follow that up with a bit about procedural programming, for the adventurous. How to structure algorithms and break them down into component procedures can be hard to grasp initially, if it doesn't seem obvious that these things are actually clearer and simpler than Goto and labels, but it's really worth taking the time and effort to find out why they are. Unfortunately a lot of this isn't stuff that can really be taught with a small number of examples of changes to your own work - you need to do a lot of reading and understand the reasoning behind the design decisions, then a get lot of practice creating such things yourself. |
| ||
Not to say about it, the only way to see if you do not use the "Goto" command in the case of shadows is to triple the code written to establish three types of shadow quality: low, medium and high, ie if I have 100 lines of code to do it without the goto command, would have to do 300 lines of code, this is just one example, since there is no other way to do it. |
| ||
First can you imagine that goto doesnt exist and that all you have is gosub? This is important, with goto you have sent the program flow somewhere else, and cannot simply get it back to where you where, but gosub lets (makes) you bring it back. so Goto cargando ... ... .cargando ... ... Stuff after cargando becomes Gosub cargando Stuff after cargando ... .cargando ... return Now in the goto example to read your program I need to find and go to cargando and continue reading from there. In the gosub example, if I can assume cargando works, then I can just continue reading the program knowing that the next command is the one that will be after cargando. Gosub is more like reading a book, you get to something with an appendix note (1), and when you have read the appendix, you go straight back to where you where. Goto is not as intuitive when reading (2) (3) And that means this bit makes nonsense, unless you actually went and read the appendix. Now as most programmers will tell you, MORE time is spent re-reading a program than writing it, so dont use goto cos it makes it a lot harder to read. Select Case. if a =1 gosub/goto One else if a =2 gosub/goto two etc Select A Case 1 Print "Mission 1." Case 2 Print "Mission 2." Case 3 Print "Mission 3." End Select http://www.blitzbasic.com/b3ddocs/command.php?name=Select&ref=2d_a-z Gosubprogram, Go-subroutine = Function (ish) Gosub label ... ... .label return DoFunction () ... ... Function DoFunction () End Functionhttp://www.blitzbasic.com/b3ddocs/command.php?name=Function&ref=2d_a-z (NB You cannot just DO this thou, because inside the Function only certain of your variables exist, but you need to learn which exist, and why) To be Turing complete, it is enough to have conditional branching (an "if" and "goto" statement), this basically means that if and goto in a language is enough to ensure you can do everything that any other language can do, you you can nearly always solve your problem with these. AND in some ways this would make you a better programmer than most. In most cases you would just endup modelling the higher level commands, which is a waste of effort. (And no one will read your listings) (1) A note at the end of the chapter or book (2) When writing it is. Because you just continue to write where ever you are, but as you can see it has made reading this a lot harder than it needs to be. And the only way to get back to where you where is to have another appendix note lining back into the text (3) |
| ||
I never ever use goto/gosub, and haven't done for over 10 years (at least). There is always a way to avoid them, and once you've done so for a while you never even think of using them. |
| ||
Me either... YUK! They are left-overs from when languages were birthed and goto is pretty much completely responsible for what is termed "spagetti code." I like to think that Methods and Functions and more advanced controls such as For, While, Repeat, Select have completely obscured the need for goto/gosub. Why is Gosub no good? it forces all your variables to be global in scope because you cant pass a variable to a gosub Why is Goto no good? because it obscures program flow (lack of structure).. which is not readily apparent in small programs but becomes a nightmare in larger ones. |
| ||
Well thank you for your help with this, I'm not a programmer, just pretend to be and I'm learning. It is clear that a solution to the problem look like option to use "Goto" and I suppose that the practice will prove me right, and that the only way to learn is to deal with thousands and thousands of lines of code and learn to solve problems the best way. |
| ||
Let me add a further comment here. While GOTO is a NOGO in a wide area of professional Programming, we should not forget that we're BASIC Programmers. Why are we BASIC programmers? Because testing, editing and runnig code is much faster than any other System. Hit F5 and you know if it'S gonna work almost immediately, where all the other language compilers that I ever tried in the past ()eg. vc++, will make a big deal out of the slightes hello world program, and if you once got everything right in your code, includig access paths to includes, linker etc. it still takes seconds to compile a 1 liner. If you for exampe try to design something in 2D, you can do that quickly in BASIC. So I think GOTO can be useful, especially for blockmarks. When you want to try two variants of some 2D commands, GOTO is the quick solution. You could also put them in functions, but it's already more work and you got to declare Globals and locals to make it work. These are simple things that you want to try in seconds, or skip it using GOTO, compare and finally delete all but the stuff you like. I do agree, GOTO should not be part of your Program Flow Structure. Nevertheless, you may use it here: for x=0 to 100 for y=0 to 100 for z=0 to 100 ... if b=1 then goto .myexit1 next next next .myexit1 But you can also do this the "legal" way: for x=0 to 100 for y=0 to 100 for z=0 to 100 ... if b=1 then exit next if b=1 then exit next if b=1 then exit next where in my opinion version B is not only longer and slower, but also uglier. Probably RETURN could be used to do something like that, but then you need to put the for loop into a function, which would only complicate the structure. So my conclusion is: there may be uses for GOTO, but they are really limited. |
| ||
Heh, JFK, I think you need to try some more languages if you're comparing Blitz3D to VC++... there's rather a lot in between (and to either side - yes there are faster prototyping languages even than Blitz). Actually I'd go so far as to extend the point of the above post one step further: Goto is close to being an ASM instruction, because the one place where its use is fully justified is when (as in the above example) the language doesn't have the feature you actually want (and you want to structure the code as if it did, of course). One nitpicky thing though as well from the above: you got to declare Globals and locals to make it work Using Globals is also generally considered bad practice, for the same reasons as using Goto: complicates control flow and hides actions off the track of execution. That said, again its use in Blitz is generally excusable as Blitz3D doesn't provide any OO or functional features, so again, there are a rather limited number of ways to achieve some things. But Globals are massively overused by beginners (I blame the examples and tutorials). A beginner shouldn't need to use Globals for simple test programs at all. |
| ||
i disagree with the nogo statement for the use of goto , its a simple Asm instruction jo,jno,jns,jbe,jl,jne and its fast if the cpu not reload the instruction cache ,or reload the pipeline . if you ever disassembled a x86 file you see much jumps in the source , also esp.x86 cpu are desingned for . |
| ||
Hey, don't take my globals away :) I love them. Seriously, when there is a variable that several functions need to access, I would have to put it on the stack again and again, as function parameters. For me a global is some kind of passive parallel thread. I think sometimes efficiency must be paid with additional, complicating dimensions. |
| ||
Hi Panno. But you have to agree: GOTO may be used like JMP, but normaly you would use a conditional jump in ASM, like JLE or so. But in Basic you'd have to IF and then GOTO, resulting in many assembler commands, including register loading for every single comparation. But I must confess, I was writing ASM programs in basic, using the peek poke goto equivalents. This way I was able to write complex programs in some sort of "interpreted ASM" without a single comuter crash, and I think you would agree that ASM coding normally is linked with tons of heavy crashes, such as complete freeze etc. Hey, why did none write an ASM Interpreter yet? At least I never heard of anything like that. |
| ||
tons of crashs ?? MEGATONS !! |
| ||
i disagree with the nogo statement for the use of goto , its a simple Asm instruction jo,jno,jns,jbe,jl,jne and its fast if the cpu not reload the instruction cache ,or reload the pipeline . true :Dif you ever disassembled a x86 file you see much jumps in the source , also esp.x86 cpu are desingned for . although if you are using a HIGH level, structured (albiet non oop) language you still should have no excuses for a goto (except perhaps jfk's exit-exit-exit loop, but even then i would be cringing when i implemented it. If evoulution were programming languages then goto would in the "goop" attempting to have a proper organism. I have a -little- more respect for gosub because it is technically a parameter & scope-less function, but even so. Whats the point in using it when a language has functions, and structured logic implementation? Last edited 2010 |
| ||
I have never used these commands in blitz. The last time i used them was in basic on the C64, a long long time ago :) First learn about using functions, then learn about types. Learning how types worked was hard for me, but once you get them they are magic. Last edited 2010 |