lambda , function , mapcar , a
hiI can see mapcar, apply and foreach are used to tolorarte a list, but still not sure what is the difference. What mapcar can do that apply or foreach cant?
And secondly some codes use lambda and some function(). Why?
Thanks
Shay Mapcar and foreach are simply loops through a list (or in mapcar's case one or more lists). I've done a description of the main differences between the 2 here: http://www.cadtutor.net/forum/showthread.php?47026-Difference-between-foreach-and-mapcar&p=404821&viewfull=1#post404821
Apply, is a way of sending a list as arguments to a function. E.g. The following would give you the same result, as they do the same thing
(+ 1 2 3) ; Returns 6(apply '+ (list 1 2 3)) ; Returns 6The reason you'd use apply instead of simply writing the normal call is, sometimes you don't know what contents are in the list or you obtain the list from somewhere else. Note also the single-quote before the +, this is a shorthand way of writing
(apply (quote +) (list 1 2 3))Quote is a bit difficult to understand at first. A way of thinking about it is that it sends the container and not the value. In lisp (especially AutoLisp) it's impossible to pass something "by-reference" as you can in some other languages. But the quote idea gets around that issue, by passing the container itself. That way you can even modify the container's contents. E.g. say you want to add 2 to the contents of any variable you send to your function:
(defun Add2 (var) (set var (+ (eval var) 2))(setq n1 5 n2 3)(Add2 'n1) ;Returns 7, but also sets n1's value to 7(Add2 'n2) ;Returns 5, but also sets n2's value to 5Note the use of eval. It's basically the reverse of quote. I.e. extract the value from the container.
Lambda, is basically the same thing as defun - except you don't need to give the function a name. I.e. it's an anonymous function. This allows you to place the definition of such function directly where it's used. Function, simply optimizes a lambda so it performs as close as possible to a real defun - since a lambda is stored as a list which needs to be evaluated, but a defun/function is stored as a somewhat compiled piece of program. Also if you're using VLIDE then you can step inside a function-lambda during debugging, but not inside a non-optimized/quoted lambda. Also function already quotes the resulting optimized lambda so it can directly be passed as an argument.
E.g. this would add 1 to each item in a list (not modifying the original list) and return the list of results
(setq lst (list 1 2 3)) ;Creates a variable (lst) with its contents set to (1 2 3)(mapcar '1+ lst) ;Runs the 1+ function on each item in turn and returns (2 3 4)But if you wanted to add 2 to each, there's no pre-made function for that. So you have to make one:
(defun 2+ (num) (+ num 2));; And then you can call it the same way(mapcar '2+ lst) ; Returns (3 4 5)But rather than make all sorts of new functions which might clutter the namespace (i.e. all the symbols known to Lisp), you can incorporate the definition of the function directly in the same line as the mapcar by using lambda:
(mapcar '(lambda (num) (+ num 2)) lst) ;Returns (3 4 5)And then if you want it to run as fast as possible and be able to debug it in VLIDE:
(mapcar (function (lambda (num) (+ num 2))) lst) ;Returns (3 4 5) Great explanations Irné, clear and concise.
Bookmarked!
Thanks a lot for this detailed explanation, ive learned a lot reading it but still i feel that i missed few things on the way...so i start building my understanding from the beginning
Right or wrong....appreciate any input
The interpreter
The interpreter reads out the AutoCAD's command line after pressing enter, if the content is wrapped with parenthesis its being delivers to Autolisp evaluation. As for the Autolisp evaluation, the interpreter deliver data for evaluation.
Function, arguments and expressions
Autolisp understand only specific structure or formula known as an expression. The content of an expressions are function and arguments. Function is a mean of manipulating data, and arguments are the data to be manipulated.
For example, In simple math its common to write a formula like this:
(2 +3) + (2*5)
What we do is the follow:
Calculating 2 + 3
Calculating 2*5
Adding the results
In Autolisp the same logic applies but in slightly different structure:
( + (+ 2 3) (*2 5)))
The interpreter does the following:
evaluate 5 as 5 and 2 as 2
applies those numbers to the * function and evaluate it as 10
evaluate 3 as 3 and 2 as 2
applies those numbers to the + function and evaluate it as 5
applies the evaluated 10 and 5 to the + function and evaluate it as 15
Autolisp evaluation
Evaluation is actually the result of an expression or any data within a parenthesis. Note that arguments evaluated first and then applied to the function.
Evaluation prevention
Autolisp evaluate everything by its nature, so there is a need to control when we don't want things to be evaluated or skipped by the interpreter.
To prevent evaluation we use the Quote function
(Quote (a b)) or '(a b)
Variables
Variables are container to hold data. A name of a variable is always the same but the value can be change by user manipulation only.
Data types
Integer
An integer is a whole number without a decimal point and its range between 32000 to -32000. If an equation that emulate to a number with a decimal point its being dropped out, for example
(/ 15 2) evaluate to 7
Integers are evaluated to themselves.
Real
Is a number with decimal point .
(/15 2) 7.5
Note that values between 0.0 and 1.0 must start with 0 or 1,
Not .425 but 0.425.
String
A string is a sequence of data types so called characters.
Lists
Can be treated as a container that holds all kind of data types and even other lists.
Assigning values to variables
Assigning values to variables is issued by two functions combination, set and quote which form one function setq .
set means set the value of the first argument to be equal to the evaluation of the second argument.
Quote means don't evaluate the first argument
Setq means set the value of the first argument to be equal to the evaluation of the second argument but don't evaluate the first argument.
(setq v 0.734)
The argument in the right is evaluated first and sent to the setq function which first preventing the evaluation of v and set the value of v to be equal to 0.734.
Another example is when we want to add value to existing vakue of a variable
(setq v (+ v 6))
The argument is evaluated first and then sent to setq function, which in turn don't evaluate the first argument but assigning the second to the first) You're definitely on the correct track. Some notes:
Yes, Lisp uses Polish notation, also referred to as Prefix-notation. Notice in pure Polish Notation you don't need any parentheses to overrule operator precedence as you do in the "normal" infix-notation. E.g. in pure polish your formula is written as:+ + 2 3 * 2 5--> + 5 * 2 5--> + 5 10--> 15This is because pure polish means each "operator" is a binary operator and can only be applied to 2 values. Lisp allows multiple values to be passed into the "operator" (zero or more), that's why it needs to group them together and why it need parentheses in all cases.
So in the Lisp idea the following happens in your formula:
(+ (+ 2 3) (* 2 5))--> (+ 5 (* 2 5))--> (+ 5 10)--> 15But notice that most of these functions can receive more than 2 items. E.g. say you want to calculate the following formula:
10 + 40 / 4 / 2 + 2 * 3 * 5 + (30 - 5 - 7 - 2)--> 10 + 10 / 2 + 6 * 5 + (25 - 7 - 2)--> 10 + 5 + 30 + (18 - 2)--> 15 + 30 + 16--> 45 + 16--> 61The same could be written as this in polish:
+ 10 + / / 40 4 2 + * * 2 3 5 - - - 30 5 7 2--> + 10 + / 10 2 + * 6 5 - - 25 7 2--> + 10 + 5 + 30 - 18 2--> + 15 30 + 16--> + 45 16--> 61Similar lisp would be
(+ 10 (+ (/ (/ 40 4) 2) (+ (* (* 2 3) 5) (- (- (- 30 5) 7) 2))))But notice, that wherever the same function calls again as one of its arguments, these can be combined into multiple argument calls:
(+ 10 (/ 40 4 2) (* 2 3 5) (- 30 5 7 2)) samifox, you added a whole lot more to the discussion than the title would imply.Is there some reason for adding all this here?Are you trying to develop a book or something?You mention reals, but give the same example as for integers, implying AutoLISP will read your mind.It won't of course.Strings have to be in double quotes, not just a series of adjacent characters. Numbers between -1 & 1 need the lead zero, right?It seems to me that the integer limit is significantly higher than +/-32000, but I don't recall the limit just now.Perhaps someone else can provide that. It looks like its range is -2147483648 to 2147483647 inclusive on my machine. irneb, I hadn't really investigated Polish notation, so I didn't know it was more strict in its use of the arithmetic functions.I've always liked that LISP is able to apply them so succinctly. Yes, AutoLisp uses 32 bit signed integers. That is 2^31 = 2147483648 with the 1st bit signifying positive / negative, 0 taking one space from the positive side, thus you get -2147483648 through 2147483647.
Note that in general Lisp acts on integers and reals transparently. By converting the result into the most accurate / largest scoped operand E.g.
(/ 1 2) ; Returns 0 integer(/ 1 2.0) ; Returns 0.5 realThis is a bit different from other Lisps. E.g. using some implementations of Common Lisp you would get a result which uses a fraction data type:
(/ 1 2) ;Returns (1 . 2)(/ 4 2) ;Returns 2(/ 32 12) ;Returns (8 . 3)
Also in AutoLisp an integer never grows beyond its limits. Rather you get an overflow, e.g.
(+ 2147483647 1) ;Returns -2147483648In other Lisps you generally get a larger sized integer. E.g. the above might be converted to a 64bit signed integer result, or even a BigInt.
But you are correct about data types. They're not all interoperable. You can't simply add a string to a real, you need to convert either one into a compatible type. This has become a heated debate over several decades: dynamic / static variable typing. Dynamic means a variable can be assigned any type at any time throughout it's life, while static means a variable is declared to only contain a specific type and is not allowed to receive anything else.
The argument goes: dynamic (as in Lisp) saves programmer's time by needing less verbosity and eliminating the need to declare all variables with their types explicitly specified. Static allows for compile time type checks and makes things like IntelliSense (in Visual Studio) a lot easier. Some languages (like F#) goes a middle ground by using inferred typing - i.e. the first time a variable is used it is stuck with that type assigned to it and will error if you try to assign a different type to it later.
With Lisp you can assign anything to any variable, but it might error if you try to use an incompatible type in a function which expects something else. This error (due to dynamic typing) only happens once the code runs, you don't get a warning about it like you do in C# (even before you've compiled). So in Lisp you sometimes need to write some run-time type checks, e.g. using the type function, or even listp / atom / numberp.
True. Even using non-strict Polish means you need to group multiple operands by using parentheses - which is what Lisp does. The only difference would be where you place these. The normal extended Polish notation is like other languages would do:SumAll(1, 2, 3, 4)While in lisp the parentheses surround both the function and the operands:
(SumAll 1 2 3 4) While the usual use of quote is to prevent evaluation (or rather defer it until later), it's not the only use. A quoted symbol does not even need to have a value at all. E.g. the types returned by the type function is quoted symbols with no value(setq test 123 test2 "A string")(type test) ;Returns 'INT, but ...(princ INT) ;Prints nil(princ 'INT) ;Prints INT(type test2) ;Returns 'STR, but ...(princ STR) ;Prints nil(princ 'STR) ;Prints STR, BUT ...(= 'STR 'INT) ;Returns nil(= STR INT) ;Returns TThis can be used to make much more efficient comparisons. You can use a quoted symbol as a piece of data, this means it uses less RAM but also when compared to another uses less CPU. A normal value would need to be checked for its symbol, then from that the RAM position needs to be extracted and finally the value stored in that position in RAM needs to be extracted - only then can it be compared to something else. Comparing 2 quoted symbols means 2 of those steps are eliminated.
页:
[1]
2