I would like to see a solution to Exercise 5 at the end of Chapter 6 in the 2007 edition of the Maple 11 Introductory Programming Guide. It's on page 255. My humble attempt is:
View 4937_Chapter6Exercise5.mw on MapleNet or Download 4937_Chapter6Exercise5.mw
View file details
I am asking this question because in the past the answers have been way cool, magic happens! I hope that this doesn't discourage any answers.
Comments
Means, 2 ways
I guess this is cheating?
Means := proc(L::list(list)) map(Statistics[Mean], L) end;Otherwise I guess I would write
Means := proc(L::list(list)) map(proc(L1) local i; add(i,i=L1)/nops(L1) end proc, L) end proc;Note how my code is as close to the mathematical definition as I can make it -- and eschews CSisms like explicit loops. My bias: you are well on your way to 'get' Maple when you cringe whenever you are obliged to write an explicit loop.
leaner and meaner
How 'bout
I wouldn't recommend that for production work, but it is nice and short and does the job.
Gorgeous!
I am jealous. I wish I had thought of that.
Arrgghh
Alas, it looks better than it works. I had tested it, but with several others, at once, and didn't notice that it didn't actually work. `+` doesn't work on a list, but rather on a sequence. It can be salvaged with
but that isn't as nice looking.
Nothing should be considered
Answers 2 and 3 should be modified to work for an empty list. For #2, this is simple. For #3, the beauty is lessened, unfortunately.
types
Which was why I suggested it wasn't appropriate for "production". That and the complete lack of type checking. I haven't read the actual problem statement, does it define what to do with an empty list? Note, also that the empty list [] type-matches list(list), so that must be dealt with as well. Possibly the input arguments should be declared as list(list(algebraic)).
'getting' Maple
Thank you, thank you, thank you, ...
Cheating, what is cheating?
I assume that CSisms refers to the C programming language and not Caesars, the emperors of Rome. CSisms is a cool word. Why isn't the word "Cisms"?
http://en.wikipedia.org/wiki/C_(programming_language)
I hope to 'get' Maple one day.
This: "Means3 := curry(map,`+`@op/nops);" is magic. I have no idea how it works. Finding out will entertain me for some time. I've read the "curry" help page once but once isn't enough. I'll have to read it a few more times. That Morse Code stuff at the end of the "curry" help page looks cool too.
I wrote "local i::integer,positive,"... I don't think that that does what I wanted. How do I declare a local variable to be a positive integer?
Is declaring a local integer variable "i" a CSism?
CS = Computer Science
So CSisms means issues that only matter from a computer science point-of-view. Loops are an operational concept which is forced upon us by sequential computers, not an issue that should matter when solving mathematical problems.
Declaring your intent (that i is a positive integer) is a mathematical concern. Nicely, Maple (finally!) lets you do this.
BTW i::And(integer, positive) is one way to say that.
Positive integers and others
Please see ?posint
J. Tarr
passed vs _passed
posint does just what I want.
i::And(integer, positive) looks like it could be very useful in cases where the equivalent (posint) doesn't exist. i.e.: posreal::And(numeric,positive)
Does assume() have an application in this area? I've tried to use assume() several times and it didn't make-it-happen for me.
When should _passed (args) be used rather than something like the passed that I used?
Can _passed be typed? Should it be typed? Would typing _passed be a good thing?
_passed
Typing _passed makes no sense and cannot be done. _passed, which is equivalent to args (an older name for the same thing), is a special symbol assigned the sequence of arguments actually passed to a procedure.
The expression _passed(args) is equivalent to args(args). I doubt there is ever a practical use for that construction.
Means3 := curry(map,`+`@op/nops);
I've been looking at the subject line for a while now.
In that line nops causes the sums to be divided by the number of terms in each sum to produce the desired means. I would like to know if there is a way to divide the sums by the number of sums, lists or columns. The input is a list of lists. Is there a way to divide the sums by the number of lists rather than by the number of terms in each sum?
I happy that the subject line doesn't work this way but, I don't understand why it doesn't. Does Maple know that that would be silly and means are obviously desired? Naa...
No one would ever want to do this except for someone who wanted to be able to get Maple to do whatever he or she wanted no mater how whimsical.
puzzle
Rather than tell you the answer, I'll give you a hint. You can modify
to return a "procedure" that divides by the number of lists, rather than the number of items in each list, by shifting the position of one character. That is, move one of the characters in the code.
Means3
"Does Maple know that that would be silly and means are obviously desired?" No, emphatically no! Never forget that Maple, despite all its power, has absolutely no intelligence. It has no idea what you want to do, and it is just doing what you tell it to do. In those cases where it does try to guess what you meant rather than what you wrote (e.g. in parts of the Standard GUI) the results are often disappointing.
You have to take a look at what Means3 actually is, and work out what it does. The "curry" is just a convenient way to produce a procedure without using -> or proc. For the understanding of Means3, it's probably better to look at the direct definition.
So here's what happens when Means3 is given a list of lists:
The "map" applies its first operand, the function (`+`@op)/nops, to each operand of the argument [[a,b],[c,d,e]], i.e. to each of the lists [a,b] and [c,d,e]. `+`@op adds the members of the list, since "op" turns the list into a sequence and `+` does the addition. "nops" takes the number of operands of the list. Thus (`+`@op)/nops adds the members of a list and divides by the number of operands.
If, let's say, you wanted to divide by the number of lists, that number is "nops" of the top-level list. So you don't want that part to be mapped. You could use
or more directly
multiplication distributes over lists
To the careful observer, there is at least one piece of magic remaining in Robert's explanation. That is, Maple automatically distributes multiplication (and division) by numeric values over lists. For example,
3*[a,b,c]; [3*a, 3*b, 3*c]This does not occur for elements that are not of type numeric, nor if any term (besides the list) is nonnumeric, unless one of the elements is equal to zero. Nor does it work over sets.
3*I*[a,b,c]; 3*I*[a,b,c]; 3*a*I*[a,b,c]*0; a*[0,0,0]In the first assignment to Mean4, curry(map,`+`@op)/nops, nops returns an integer which is then distributed over the list(list) structure.
"curry" is just ...
Your understanding of Maple is so much better than mine that you will never and can never know how much that helped. Thank you all, Robert Israel in particular.
Although the magic is no longer so black, this:
Means3 := () -> map((`+` @ op)/nops, args);
still seems miraculous because the function, (`+`@op)/nops, needs and gets the elements of args, the lists not the list of lists, in two places.
The map help page says the equivalent of:
"map(fcn, expr) executes fcn(elem) for each element ..."
if doesn't say:
"map(fcn, expr) executes fcn(elem, elem) for each element ..."
Also, in the case of the test data that I used ([[1,2],[1,2,3]]) is (1+2)/2 computed or is 1/2 + 2/2 computed? From the output that results from printlevel:=1000: I think that (1+2)/2 is computed. So, is division being distributed over the elements of the list?
applying arguments to expressions.
The reason it works is that Maple can apply arguments to an algebraic expression. See ?evalapply for details. For example,
(3*f+a/b)(1,2); 3*f(1,2) + a(1,2)/b(1,2)Division by a numeric quantity is distributed over a list. See my previous response in this thread.
Distributed Division
In the following worksheet printlevel:=1000: shows that in the last expression 3 and 6 are computed. So in that case, which is what curry(map, (`@`(`+`, op))/nops) yields, the division is not distributed.
View 4937_Chapter6Exercise5a.mw on MapleNet or Download 4937_Chapter6Exercise5a.mw
View file details
yeahbut
Yes, but that is because there is no list to distribute over. `+`@op([1,2,3] evalutes to 6, which is then divided by 3 (nops([1,2,3]).
OK
Thank you.
It's hard for me to tell what's going on even with the printlevel set to 1000. Apparently I did see the values 3 and 6 evaluated.
It has been said about lisp practitioners, probably by C or assembly programmers, that they “know the value of everything and the cost of nothing.” Computers are so fast and numerous these days that no one would say that anymore.