![]() |
sponsored links |
|
|
sponsored links
|
|
1
1st June 16:12
External User
Posts: 1
|
{{Date: 15 Jul 2003 10:39:45 -0700
From: viator@rediffmail.com (viator) I am already proficient in C/C++/Java but the philosophy of LISP seems different and a little mysterious to me.}} The jargon "place" means some computer memory where you can store data that may change from time to time during program execution. The most common place is a variable, for example the varible X can have the value 3.6 then later change to 10.2 because of an assignment statement. But there are many other kinds of places in programs: Cells in an array (including a vector which is a one-dimensional array, and a string which is a vector of characters), slots in a structure, bytes in a machine word, ... The philosophy of LISP is that a place can hold any type of data whatsoever, the technique being to hold a type code together with either the data itself (if it's very small, for example a small integer or an ASCII character) or a machine address of the start of the data elsewhere in memory (if it's not very small). Return values from functions, and arguments to functions, work the same way as places. Functions that process data generally look at the type code to decide how to process the data, for example the function + can add any combination of types of numbers, so it checks the type code of each argument first to make sure it's a number (signal error if not) then to see what coercion ("implicit casting" is the C jargon) is needed to make the various arguments compatible for adding them together. The philosophy of C C++ FORTRAN BASIC ALGOL COGOL etc. is that a place can hold only one type of data, which must be declared at compile time, and the code generated by the compile is capable of handling only the one type of data it expects. This same applies to return values from functions and arguments to functions. In C++ there's a way to set up more than one type of data for a given place, whereby the application programmer must ********ly enumerate the various types that are allowed, and the compiler then jury-rigs type codes for just those particular types that must be checked at runtime to dispatch to the appropriate object-function. This is generally a royal pain, so if you're going to have lots of such places you may be better off programming the whole thing in LISP from the start. In LISP there's a way to declare the type of a place, and if the only references to this place are all declared the same, and if the particular type would allow more efficient code if done the C C++ etc. way, then the compiler will then put untagged data there and generate that more efficient code. The only place this is worth doing is in tight loops where arithmetic will be performed very many times, and even then only if the overall program seems to be a bit slow and you need to make it faster. Profiling the code can show which parts of the program are executed the most times, thus direct you to speeding up just those parts. The other big difference between LISP and other languages is that in LISP there's a standard way to represent program structure as data. The READ function can read in an s-expression from a source file, and looping on READ can read in an entire source file to create a list of everything in the source file. (Caveat: If the source file uses readtime macros or conditionals, you get the result after those have been applied, rather than the source going into them.) An ordinary user can then write code for browsing the program structure in any way desired, making changes as desired, writing out a modified program if desired, something basically not possible in any other language. (If there were readtime macros or conditionals, it's a bit more work to make changes to the file. You'd have to read the file as a string, find the places that need changes, use FORMAT-TO-STRING to create the replacement for that part, and then piece together the unchanged and changed strings to create the updated file. This still beats the other languages where you can't do the task at all.) in later to create an exact copy of what you originally had in memory. If you need to study some data file in some other format, the usual way to do it in LISP is to write a parser that converts that data format into some structured representation inside LISP. Once that's done, you can do all study of it per the structure instead of per the original linear sequence of characters of the original file. Any compiler must have something like a hash table for keeping track of names of variables, so that when the same name appears a second time it re-uses the same variable as before instead of mistakenly creating a new variable by the same name as before. In other languages, this hash table is available only in the compiler, and only for that one purpose, whereas in Common LISP, hashtables are generally available to all programs in case they should ever need one, or in case the user might want to type in the name of a variable and thereby obtain access to the actual variable of the program instead of a new copy by the same name. All the tools of LISP are available from a single program environment, including the compiler and loader and EVAL and READ and the printing functions, so you don't need separate compiler and linker and runtime programs, and you don't need an IDE to coordinate the separate programs (or alternately shell commands or GUI clicks to manually switch back and forth between them). You don't even need to use the system or IDE 'make' or "rebuild project" utility to maintain large projects, since testing date-last-written and calling compiler as-needed can all be programmed from within LISP, or if you do choose to use the 'make' facility you can invoke it from inside LISP, so it can be part of some user action which does the make then does what the user asked for, lessening the chance the user will forget to do the make first. The really neat thing about LISP (in addition to all the above), is that compiled code, interpreted code from files, interpreted code keyed in or pasted in, and interactive calls to functions, can all be intermixed freely. Typically the most stable part of my program is compiled, and a patch file containing things I believe are working overlays that, and my current-session patches overlay that, and I'm constantly trying new lines of code and combining them into new functions to test, which then eventually miagrate to the current-session patch then to the main patch file then to the main compiled file. Oh, one other wonderful thing about LISP compared to all those other languages: You don't have to specify at compile time how much space will be needed for each item of data, such as a string or array. Everything (except tiny data that will fit within a tag+tinydata word) is allocated at runtime (tiny data, and tagged pointers to allocated data, are on the stack or in registers when being passed around), and automatically recycled when no longer accessible from the program. So for example, if you want to read a line from a file, you just set a variable to the result of (READ-LINE <filehandle>) and never have to worry about overrunning a buffer you allocated. Compare this to C where you have to do fgets(&array,maxchars,filehandle) or somesuch and somehow handle the case where the line wouldn't fit within the space you allocated. Likewise, to concatenate two strings in LISP, you just concatenate them and store the result in a place, and don't worry how long they might be, and never have to pre-allocate space to store the result. Likewise if you do an integer arithmetic operation, you get the correct result even if it won't fit in a machine word, it allocates a BIGNUM if needed to store the correct result. You also asked about Java. I've never had any access to Java, so I can't say how it compares to LISP on one side and C++ as the nearest on the other side. I've heard it has automatic storage allocation and garbage collection, like LISP. I would guess it does *not* have anything like LISP's standard internal representation of the structure of program code, i.e. READ and PRINT, somebody correct me if I'm mistaken. Maybe somebody else can say how Java compares on the other points I raised. |
|
|
|
3
1st June 16:12
External User
Posts: 1
|
eric3057@yahoo.com (Eric Smith) writes:
No doubt. However, good programmers start to get benefits almost immediately. Even in a smallish project, you usually pass the break-even point, where the Lisp newbie benefits from the change of language. This argument made a lot of sense, back all of 3 years ago, when there was an amazingly large supply of capital for programming projects. However... .... maybe it's just where I'm at (the SF Bay Area), but $0/hr isn't very compelling. For me, one major benefit of Lisp has been being able to make bids/estimates for projects, that are an order of magnitude smaller than the C++ bid. I guess it would seem nice to get paid for 10x as long, but in reality that's not going to happen. In this case, Lisp lets me be a superstar: I can do the project at all. -- /|_ .-----------------------. ,' .\ / | No to Imperialist war | ,--' _,' | Wage class war! | / / `-----------------------' ( -. | | ) | (`-. '--.) `. )----' |
|
|
5
1st June 16:13
External User
Posts: 1
|
tfb@famine.OCF.Berkeley.EDU (Thomas F. Bur****) writes:
Double your price and see if they still buy for a 1/5 at least half as much as 1/10. You are really lowballing your self. marc |
|