From: Sean Middleditch Date: 2002-04-07T03:08:59+09:00 Subject: Re: Is eval a code/design smell? On Sat, 2002-04-06 at 12:41, Tobias Reif wrote: > Sean Middleditch wrote: > > >>>if you provide a schema in non-code > >>>format, > >>> > >>you mean non- Ruby code? > >> > > Ya. > > which format for example? Whichever - XML might work, by dumping the tree nodes. I did that with a mini-language I wrote a while back (to help facilitate in sending pre-compiled chunks across the network, for some really nifty distributed computing.) > > > > Na, I was saying that how you were concerned with speed, pre-parsed > > loads even faster. > > > So currently I seem to have a good compromise between > "security" (generated code is written to a file, in a human readable > form, not silently evaled in mid air, or compiled into unreadable > bytecode) and > "speed" (libs are generated only once). Yes, I suppose you probably are at the best you can be right there. You also are loading the libraries, not evaling them (requiring is done at compile time, right?) > > > > Heck, I almost never compile source code when installing software - I > > jsut apt-get it into place. But I know if I need the source (which of > > course happens every now and again) I can get it. > > > But we're talking about Ruby; what does this mean then? Just an example of that distributing Ruby code in binary format doesn't mean you're not open source, like you implied in the paragraph you cut out. > > "methods for quickly, easily, and powerfully constructing classes at > runtime with sending untrustable content to the parsing engine." > > What features are you proposing; exactly? (I really am interested in > seeing actual code examples.) OK, say you have a method 'dothis' you want in a class: def dothis (a,b) a+b*c end Now, you can easily add that to a class, with (for example), and use the function, like this: myclass.dothis = dothis myclass.c = 10 print (dothis (1, 2)) And have that print 21. In another example, say you have code that asks a user for a command, takes that command, and calls a similarly named method in a Command class: comm = get_user_input () Command.call_method ('comm_' + comm, arg1, arg2) Which is pretty much wht Ruby already provides with signals; just nobody seems to understand or use them in all the ways they could be used. (Since everybody complicates things by constructing the method calls themselves using eval()). The point I'm trying to make, tho, is that passing strings to eval() to be parsed isn't necessary, because you can dynamically generate all the classes/code you need from pre-parsed code. That's my gripe with eval() - it's not preparsed code. And, eval() offers rooms for too many uncatchable bugs, thanks to string expansion, and untrustable input. When all the executable code is the code the programmer entered, and all the user provides is the data (which can be converted to indices or method lookups in a safe fashion), I again see no need for eval(). Accessors, of coure, can be made directly into methods at compile time. Mathematical expressions could be passed to a math library (possibly the GNU math utils, or whatever - it's not hard to write one) that doesn't have the ability to run arbitrary code. If you need variable expansion in user input, it would be better to parse those out yourself and use a special hash or other construct for finding the variables, because then input can't access arbitrary data (i.e., and the username/password data from a database connection object the code is using). Ruby provides, in *most* ways that I can tell, what we need to not use eval(). The other few things seem to be design issues that I'm not too familar with (i.e., do accessors really call eval at each usage during runtime? I should probably grab the latest source and check...). > > Tobi > > > -- > Neither simple nor complex matters are to be complicated. >