Why lisp?

Started by
103 comments, last by Vlion 20 years, 1 month ago
quote:Original post by Nekhmet

This is the right notation for the job. My error rate has dropped to almost zero - when it was almost impossible to get things right before. I can add new rendering modes effortlessly.

To make it happen, though, I had to write a whole fricking compiler.


Why did you need to do all this for something that most people would just wrap in a function? Do you really need to be able to change all this outside the program?

[ MSVC Fixes | STL Docs | SDL | Game AI | Sockets | C++ Faq Lite | Boost
Asking Questions | Organising code files | My stuff | Tiny XML | STLPort]
Advertisement
You mean write a function for each rendering mode? There would be the same possibility of error - when writing the function, I could forget to disable the stencil buffer, for example. It would be equally error-prone.

- Josh



[edited by - Nekhmet on February 29, 2004 12:01:59 PM]
Maybe I''m missing something here, but it sounds really simple to me. You write one function that sets everything to your defaults, and call it before you set your mode specific values. This is basic programming.

resetState();
enableLighting();
enableStencil();
etc...

How is that more error prone than creating a ''little language''?
The resetState method is a little more complex than you think, given the constraints:

* guaranteed determinism required (everything in default state unless I specifically mention it)
* minimize number of state toggles
* one I didn''t mention: vertex programs and fragment programs must be compiled in advance, I''m assuming that compiling a VP isn''t that fast.

For example, let''s say that "resetState" says this about lighting:

glDisable(GL_LIGHTING);

And let''s say I do this:

resetState();
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

At this point, the code *appears* to have enabled one light. But, it contains a bug: at this point, several lights could be enabled, because resetState never disabled light1-light31.

So I could change resetState to look like this:

glDisable(GL_LIGHTING);
for (int i=0; i<31; i++) glDisable(GL_LIGHT0+i);

But now I''m doing 32 unnecessary state-setting operations in a very common case, namely, when lighting is off. I could minimize the state-setting as follows. First, keep one set of global variables indicating OpenGL''s current state. Second, keep a parallel set of global variables indicating what I desire it to be. Write an "applyState" function that compares the desired state to the actual state, and surgically fixes the actual state. Given this function, rendering would look like this:

resetState(desiredState);
desiredState.Lighting = true;
desiredState.Light[0] = true;
applyState(desiredState);

We probably want to move some of this code to initialization time. Vertex programs can''t be compiled at render time, this has to be done at initialization time. Second, these state-structs are gigantic, so it''s probably faster to set them up at initialization time. Let me alter the code:

initialization code:

// "resetState" is faster if called at initialization time:
// "compileVertexProgram" cannot be done at rendering time:
resetState(renderingState1);
renderingState1.Lighting = true;
renderingState1.Light[0] = true;
renderingState1.FragmentProgram = compileFragmentProgram("....");

at render time:

// Don''t know camera position at initialization time:
// Don''t know the texture at initialization time:
renderingState1.ModelView = currentCameraPosition;
renderingState1.Texture[0] = currentTexture;
applyState(renderingState1);
glDrawElements...

Unfortunately, now I''m back to where I started: I have a global state, which I''m modifying incrementally. I''ve lost my guarantee of determinism. I can fix this too, by copying the rendering state into a local variable and then modifying it locally:

{
RenderingState renderingState1a(renderingState1);
renderingState1a.ModelView = currentCameraPosition;
renderingState1a.Texture[0] = currentTexture;
applyState(renderingState1a);
glDrawElements...
}

Ideally, I should make the global rendering states "const" so that I can''t accidentally alter them, which would be a likely occurrence, given that I''m typing "renderingState1a.x=y" over and over. A one-character brain-fart would alter the global variable.

This solution is clearly sensible - a viable option. Which solution is better?

Well, given C++, obviously, this solution is better. It''s easy to program this solution in C++, hard to program the little-language solution. In fact, I''d say, I spent way too much time programming the little-language solution, if I had it all to do over again, I''d do it this way.

Which is better if you''re using Lisp? In Lisp, both solutions are equally easy to program, so the decision wouldn''t be made on the basis of programmer time. Instead, you would choose based on which notation you think is more elegant and expressive. I suppose that''s in the eye of the beholder.

To me, the point of it is that Lisp allows me to use little-language solutions. If you''re a Lisp programmer, you soon find yourself using little languages quite a lot. Even people in the C++ world use little languages occasionally - witness Corba, SQL, etc. But they don''t use them often, because of the high barrier to entry. Are they really an "important" tool? If you ask a Lisp programmer, he would say definitely. Can you do without? Of course.

- Josh




quote:Original post by Krippy2k
Maybe I''m missing something here, but it sounds really simple to me. You write one function that sets everything to your defaults, and call it before you set your mode specific values. This is basic programming.

resetState();
enableLighting();
enableStencil();
etc...

How is that more error prone than creating a ''little language''?


If enableLighting throws, then your program is in trouble. You may need to unwind the enabled items and release components accordingly before quitting. Encapsulating the enables into a single common function that accepts keyword arguments will be more extendable and less likely to have bugs.

This topic is closed to new replies.

Advertisement