Single inheritance solves the problem of inheritance ambiguity between parent classes.
I don't see the problem
Suppose I have a class name and I create a subclass place-name by adding a slot for a location. Meanwhile I need colours, both for my paints and my objects so I create a colour. Finally a create a class coloured-place-namefor named things in that are put in places and have colours, by multiple-inheritance, taking first place-name and then colour.
At this point I have an inheritance ambiguity. Obviously place-name comes first, but what next, name or colour? What I don't see is why I should care.
It is only going to matter if I have a method, act, defined for both name and colour. But how could that happen? I'm only using multiple inheritance because all three of place-name,coloured-place-name, and colour make sense. If only two of them made sense I would use single inheritance. So the meanings of act on the two classes are orthogonal, I don't want one shadowing the other.
We really have a name clash, and need to sort out our names. Perhaps act on name should be speak, and act on colour should be paint
OK the inheritance graph isn't totally ordered, but each method is only defined on a subset and, for any particular method, its subset will be totally ordered. So I cannot see a problem that actually matters in practice
Single inheritance is the one that is simple to implement. As an application programmer I want the one that is simple to use and that means not having to program around language limitations.
If you wanted to teach trigonometry using Euler's equation you would have to teach complex numbers ahead of time so that pupils would be comfortable with them.
That is probably a good idea any way. For example, turn 2+i into a right-angled triangle, two wide and one high, draw on squared paper, cut out with scissors. Do the same for 3+2i and 4+7i.
Note that (2+i)x(3+2i)=2x3+3i+4i-2=4+7i.
Place the two smaller triangles side by side to add the angles. Place on top of the big triangle and see that the angles are equal.
I think that children could grasp that there is a funny way of multiplying pairs of numbers that makes angles add up. Whether their teachers could cope with complex numbers is another matter:-)
Maybe Common Lisp source is clean and elegant or maybe it has all the charm of porridge with finger nail clippings, but all that misses the point.
Here is an example from this afternoon's coding. I'm trying to turn the Lorenz model into a musical instrument. My text book gives the differential equations as . x = p(y-x) . y = rx - xz -y . z = xy -bz
where p,r, and b are parameters and x,y, and z are variables, coordinates in a 3 dimensional space. It is easy enough to code up these equations
(defun lorenz (x y z p r b) (vector (* p (- y x)) (- (* r x) (* x z) y) (- (* x y) (* b z))))
is a function of 6 variables that returns a vector of three elements. However that is not really what I want. I want to pass in a vector (x,y,z) with my variables bundled together. So I decide that x will be component 0, y will be component 1, and z will be component 2 and code:
(defun lorenz (v p r b) (vector (* p (- (aref v 1)(aref v 0))) (- (* r (aref v 0)) (* (aref v 0)(aref v 2)) (aref v 1)) (- (* (aref v 0)(aref v 1)) (* b (aref v 2)))))
Well that is crap in two different ways. First, I'm repeating myself. (aref v 0) would be OK if I only typed it once, but repetition is bad. Second, the connection to the page in my text book is lost. I really want to be copying the equation out of my text book. I can cope with infix to prefix translation, but I don't want to lose my symbolic names. Fortunately it is easy to fix
(defun lorenz (v p r b) (let ((x (aref v 0)) (y (aref v 1)) (z (aref v 2))) (vector (* p (- y x)) (- (* r x) (* x z) y) (- (* x y) (* b z)))))
At this point one says: the three lines with aref in them are just boiler plate, make them go away! One wants to be able to code a function that is passed a vector, is written using component names, and returns a vector, like this
(defvecfun lorenz (p r b) (x (* p (- y x))) (y (- (* r x) (* x z) y)) (z (- (* x y) (* b z))))
No repetition, no boiler plate, clear relationship to the equations in the book. Common Lisp doesn't have a defvecfun command, so I add it by defining a macro
Now my ideal code (defvecfun lorenz (p r b)...) works.
Rather than manually translate the equations in my paper book to meet the syntax requirements of my programming language, I type the equations from the book into my source file without regard for the fact that I want x,y and z to be components of a vector. Then I write a bit of code, my macro, to automatica
For example you might want the programming course and the calculus course to be mutually supporting.
The rules for differentiation could be coded up in the programming language. For Common Lisp it might look like
(defparameter plus '+) (defparameter times '*) (defun differentiate (form variable) (typecase form (number 0) (symbol (if (eql form variable) 1 0)) (list (case (first form) (+ (list plus (differentiate (second form) variable) (differentiate (third form) variable))) (* (list plus (list times (differentiate (second form) variable) (third form)) (list times (second form) (differentiate (third form) variable))))))))
(differentiate '(* x x) 'x) => (+ (* 1 X) (* X 1))
But why are those the rules, rather than some other rules? Well it is supposed to agree with the numerical version
(defun numerically (function argument difference) (let ((left (funcall function (- argument difference))) (right (funcall function (+ argument difference)))) (/ (- right left) (* 2 difference)))) (defun square (x)(* x x)) (numerically (function square) 7 0.001) => 13.998031
And indeed
(defvar x 7) (eval (differentiate '(* x x) 'x)) => 14
Notice the wider vision: students are taught a programming language to give them a language in which to talk about procedures, including procedures that they are expected to master in other parts of the curriculum.
Re:You don't need new standards
on
The New C Standard
·
· Score: 2, Informative
And then there's the syntax of the language. Try writing a parser that can correctly parse any valid C program. Or try to write a program that does transformations on C programs, both reading and writing C code.
If that kind of thing matters to you, you should look at Common Lisp. The built-in programmable parser is powerful enough to parse all CL programs and is configured to do so by default. Defining source-to-source transformations with DEFMACRO is an important technique
In a world of lots of little companies, competing for customers and competing for employees, we don't need job protection laws - just get a job with a rival, or start up on your own.
In that kind of 1776-world job protection laws can do more harm than good. They make it harder to get a new job, they make it harder to set up your own business.
In the real world, where job markets are dominated by a few large companies, we do need job protection laws to protect our freedom. Or maybe we need stronger competition laws to stop a small number of large companies dominating.
There is no need for the job protection laws to apply to small companies. Indeed, if job protection laws apply to big companies but not small one, that is in part a competition law, hindering the big companies in their competition with the small companies.
The idea of a patent is that the inventor gets a monopoly that he can exploit to repay the investors who backed his research.
But what happens when a product is covered by more than one patent? Every patent holder gets a veto on exploiting every-one elses' inventions!
If you propose a program of research, hoping to create a patentable invention, your bankers will want to know how many existing patents they will have to license before they can exploit your hoped for invention. Lots of patents means no funding for your research.
The patent system can only work in the way its boosters claim if there is a one patent per product rule. Let the patent office pick a single ruling patent for each product and grant the monopoly only to the inventor of the ruling patent. Then investors can back expensive research aimed at major break throughs, enticed by the prospect of having the ruling patent, and not having to buy off patent leaches.
Short copyrights protect artists from having to compete with copies of their recent work. It gives them a business model. They can give up their day job and work full time on creation. That is good for the both the artist and the public.
Long copyrights protect artists from having to compete with old public domain works. Copyright lasts so long that only very old work is in the public domain. Old stuff gets "retired" by the copyright holders, neither for sale nor in the public domain.
That is against the public interest. If artists can produce work that is better or more up to date than good, old work, then a short term of copyright provides a business model and funding. If an artist's work cannot compete with the good, old stuff, because lacks enduring merit and also lacks shiny newness it does the general public great harm to force it onto them by retiring the good, old stuff.
Active means something like Slashdot where you get to talk back.
Now for the tricky bit. If you cannot do the active bit, will you sustain the critical bit? If you cannot call "Bullshit", you only upset yourself by watching out for it. So I doubt that one can watch TV and maintain a critical stance. Thus the answer might be that in practise it is No and No
It started with great excitement. FORTRAN, LISP, BASIC, ALGOL, PASCAL, PL/1, FORTH, COBOL. The economic underpinnings were clear enough, and had three aspects:
1)The early versions of these languages left plenty of room for
improvement. That is to say, a new improved language offered cost
savings to the ultimate users of IT services.
2)The early versions of these languages were relatively simple. It
hadn't cost too much money to develop the language that far. Those
who wanted to start from scratch on a new language had to justify a
relatively modest expense to duplicate what had already been
achieved, and could point to the prospect of large savings to come
under point 1.
3)Compared to today the languages were not widely
deployed. Businessmen did not have to think in terms of duplicate
staffing, with one team skilled in the old language to maintain the
legacy code base, while another team skilled in the new language
work on duplicating the code base, and one day moving on to writing
new code that will eventually save money.
As the years rolled by languages got better. The benefits of new computer languages were hit by diminishing returns. The threshold cost, the money you must spend to get the new language competitive with the old language, rose and rose. The installed base grew, and with it the costs of change.
A theoretical solution to these problems was the programmable programming language. Rather than start from scratch, reprogram the old language. Under the name "extensible programming languages" this idea had failed serveral times. Sticking points included:
1)Extension mechanism not powerful enough (C #define)
2)Extension mechanism too complicated(ALGOL68C,PROLOG)
3)Base language too simple(FORTH)
There is a three-way pull. The simpler the base language, the easier it becomes to make a powerful extension mechanism without it becoming too complicated.
By 1990 it was becoming clear that the CL macro system made CL into the first fully practical programmable programming language. This revolutionised the economics of programming language design. Compare making a new language feature available by starting from scratch with programming it into a programmable programming language. The advantage of starting from scratch is that you can get the syntax "just so". If you want the cost saving of using a programmable programming language, you have to accept the syntax of the base language, and some mild constraints on the syntax of your added feature. But there are savagely diminishing returns in fiddling with syntax. That last 10% of getting the syntax just so saves what? 1% of programming cost, perhaps, if you are lucky and the new syntax really is an improvement.
With a programmable programming language the "new feature" is simply a file a macro-definitions. All your legacy code still runs in the "new language". Your programmers simply have to learn the extra bit. No starting over.
A fully practical programmable programming language destroys the economic rational for programming language design. The point of a computer programming language is to save money. The point of a new language is to save more money. There is no point in trying to save money the expensive way, rather than the cheap way.
Very few persons have understood this. Programmers in other languages haven't. I don't think many CL programmers have realised either. CL is politics, not art. I think the reaction of most Lispers, to realising that not only has Lisp won, but specifically CL has won, is to say "Oh shit, if we had realised that we were going to be stuck with it for all eternity, we would have done a better job of designing it." Tough. The era of computer language design ended 13 years ago. Sorry you missed it.
Now you are probably aware that computer language desig
(defun matrix-multiply (a b) (assert (= (array-dimension a 1) (array-dimension b 0))) (let ((c (make-array (list (array-dimension a 0) (array-dimension b 1))))) (loop for i below (array-dimension a 0) do (loop for j below (array-dimension b 1) do (setf (aref c i j) (loop for k below (array-dimension a 1) sum (* (aref a i k) (aref b k j)))))) c))
You are trying to tease smug lisp weenies by saying that their language is a pure functional language. That doesn't have enough truth in it to sting or to amuse.
Now, as LISP has shown, programming straight to the AST, while it has its advantages, is a historical loser. But that doesn't make exposing it in a standard fashion a Bad Idea.
Lisp failed in the early eighties. That is twenty years ago. Things were different back then, and it is important not to learn the wrong lessons. Here are some of the reasons LISP failed.
Virtual Memory Mysticism
Four megabytes was a lot of memory back then. The junor manager could be persuaded to sign off on the purchase of a workstation with that much, but the middle manager would cut it back to two megabytes and the senior manager would cut it back to one megabyte. The fancy Lisp application would have a working set of three megabytes, so the machine would page thrash and run like cold treacle. Eventually management would be pursuaded to buy another megabyte, but it would still be too slow. The basic problem was that people treated virtual memory as magic and were reluctant to accept that there were still hard limits on the ammount of physical memory required.
VLSI killed bit slice
Back then, everybody and their dog was starting new mini-computer companies, using 4 AMD 2901 four bit slices to make the ALU and a 2910 to sequence the micro-code. The big Lisp vendors had their own hardware. Symbolics had Lisp machines, Xerox had D-machines. As the decade wore on, technology progressed, and VLSI CPU's such as the 68020 and 80386 slaughted the LSI CPU's. DEC's VAX was the biggest losser, but the Lisp vendors suffered greviously from mis-reading the way the hardware market was going.
Naive garbage collectors
Garbage collectors are hard to write. In the 80's Lisp vendors were proud that their garbage collectors were free of bugs. Unfortunately the old mark and sweep collectors tended to walk swapped out data structures, thrashing the virtual memory system. Modern generational collectors are enormously better.
Computer science was young
Many programmers were self taught. (I read mathematics at University.) Others had studied computer science, but were learning from academics who were new to computing themselves and thought PASCAL was a good language.
Why do you want access to the AST? The idea is that you can avoid manual maintainance of repetitous code and boiler plate code by automatically generating it. Well, it is a nice idea but it is also a sophisticated idea.
Some of the application is written in the base language. Some of the application is automatically generated. The generated code doesn't appear by magic. There have to be source files, in an application specific language. There have to be code generators, written in a meta language, that take the application specific language and expand it to the base language.
It is a huge win if the meta language is transforming AST's into AST's rather than transforming text files into text files. To obtain this benefit, the programmer must be thinking in terms of the abstract syntax, rather than the surface syntax.At this point it becomes natural to give up on surface syntax and program straight to the AST. It is also natural to insist that the base language is suitable for writing AST to AST transformers, so that a separate meta language is not required. This is what Lispniks are getting at when they say that Lisp is its own meta language.
This way of thinking about programming went right over the heads of most programmers in the 80s. I think that the most important reason why Lisp failed in the early eighties is that it was 20 years ahead of its time
It would be nice to be able to run your program before you have written it. For example:
CL-USER(1): (defun foobar (x) "Keep barring x until it is foo" (loop for i = x then (bar i) until (foo i) finally (return i))) FOOBAR CL-USER(2): (foobar 7) Error: attempt to call `FOO' which is an undefined function. [condition type: UNDEFINED-FUNCTION]
Restart actions (select using:continue): 0: Try calling FOO again. 1: Return a value instead of calling FOO. ... [1] CL-USER(3): (defun foo (x) "X must be over 100" (> x 100)) FOO [1] CL-USER(4)::continue 0 Error: attempt to call `BAR' which is an undefined function. [condition type: UNDEFINED-FUNCTION]
Restart actions (select using:continue): 0: Try calling BAR again. 1: Return a value instead of calling BAR. ... [1] CL-USER(5): (defun bar (x) "Grow x by doubling" (* x 2)) BAR [1] CL-USER(6)::continue 0 112
We start the program running at prompt 2, write it at prompt 3 and 5, and get the answer, 112, after 6.
This would help with one off calculations, and with refining requirements via exploratory programming. I think the issue is more of a culture/management/training thing, rather than technical difficulty.
I'm curious as to what Tyler has in mind, since Common Lisp is a strongly typed language.
Perhaps his concern is that Lisp does its type checking at run time, rather than compile time. There are two aspects to this. Some compilers, notability CMUCL, make good use of the optional declarations to do type checking at compile time and produce fast code. More importantly, the actual issue is not compile-time versus run-time,
but early versus late
You always want early type checking. If your development cycle runs: edit, compile, edit, compile, run, edit,.... then you want compile time type checking. If your development cycle runs: edit, run, edit, run, compile, run,... then you want run time type checking.
Even if the software is designed top down, a Lisp programmer would code in a bottom up, test as you go, style. One window has the program source, another has the Read-Eval-Print-Loop. Immediately a function is written, it is sent to REPL and tested interpretively. Once the code is correct, it is compiled, to get full speed, and work moves to the next stage: achieving performance goals.
Thus Lisp has early type checking, and that is what is important, not whether it is compile-time or run time.
Some industrial waste is stable. Arsenic waste from tin mining, mercury waste from gold mining, cadmium from discarded rechargable batteries, beryllium from heat transfer uses.
None of this stuff decays at all. Waste that just goes away if you wait long enough looks good by comparison.
More significantly, there is an inverse relationship between half-life and activity. When you take out your spent fuel rods there is some U235 left, with a half-life of 700 million years, and also Strontium 90 with a half-life of 29 years. The Strontium 90 with its short half-life is releasing its energy quickly. This contributes to making the spent reactor very radio-active and very dangerous. But 290 years later 99.9% of the Strontium has decayed. Meanwhile the Uranium, which is releasing its energy too slowly to be dangerous, clouds the issue of how long reactor waste lasts. Long after the waste has ceased to be dangerous, it remains slighty radioactive.
One mind boggling point is that Uranium used as reator fuel supplies about a million times as much energy per unit weight as coal. Coal is a fairly pure product and contains only about 1.5 parts per million Uranium as a contaminant. So about 50% more Uranium goes up the chimney of a coal fired power station as goes into the reactor of a nuclear power station.
That is amusing in a way, but not very important, because the Uranium that goes into a reactor isn't dangerous anyway. The worry with nuclear power is the transmutation of Uranium into short lived, highly radioactive isotopes of other elements. However the point remains that the quantities of waste involved in nuclear power are very much smaller than the quantities involved in producing power from chemical sources.
Why do I care? I was six years old at the time of the Aberfan Disaster, the same age as many of the 116 children who died, suffocated under a slurry of waste from a coal mine after the collapse of a waste tip. The TV pictures of the time showed the gable end of the children's school. It was just like the one I attended and this upset me.
I have never forgotten that quantity is a quality of waste. The waste from the coal mine might as well have been composed of perfectly safe, inert materials. It would not have made any difference. The children were buried and suffocated because there was so much of it, not because it was "dangerous" in the sense that the word is used today.
by what metric is it considered environmentally friendly?
The governments Germany, France, and Italy have all made huge
promises to their peoples of generous pensions
paid out of general taxation.
The next 30 years will see the unwinding of those promises as demographic changes make them undeliverable.
What bland words for such a dire predicament!
Who will innovate in the EU, knowing that their profit will be confiscated in a desperate attempt to pay the pensions bill. Will it even be possible to do business in countries riven by such social stresses?
The future will be made elsewhere. The blood of
the Europeans will be drunk by
monsters from the past.
There you are analysing the 6 dimensional political/social space:
socialist versus capitalist
big business versus petit bourgeois
factional versus collective
collective versus individual
homogenous versus heterogenous
Smithian versus Ricardian
contemplating the 3.7 dimensional submanifold of the chaotic attractor.
Knowledge of the dynamics lets you predict several orbits in advance that the system is going to visit an undesirable region of the attractor. No worries. Even a tiny intervention will blossom
exponentially. Knowing the dynamics you can exploit the sensitivity of trajectories on the
attractor in order to intervene cheaply and inconspicuously.
But is that the only option? Adjusting the
parameters of the dynamics will move the attractor. Events that were likely become deterministically impossible. Events that were deterministically impossible become likely.
What would a parameter adjustment look like? The oral contraceptive is an example. Fertility is
a key parameter of society, and oral contraception
makes a huge difference to the coupling constant between social pressures and individual desires for fertility and actual outcomes.
I don't have a clue how to construct a Hari Seldon style psycho-history, but that is because
I'm stupid. Chaos in dynamical systems is not the
problem.
Loo, Foo, and Poo work in the farm in Vietnam or Bangaladesh or somewhere.
It is a small farm and only really needs two to work it, so Loo goes to the
big city, learns to operate a sewing machine and gets a job in a garment
factory at a fraction f of American wages.
In USA Jane's job in the garment factory is out-sourced, so she has to learn
to do something just as boring with pipetts,
and get a machine minders job with a bio-tech company.
Jane is out $10000 in lost wages before she gets her new job so she is
pissed
Short term outsourcing sucks, but who are the winners and losers long term?
Well the garments are still getting made, and Jane is doing a real American
job that wasn't getting done before, so the world economy is up by the
production of an American worker.
That is a pretty cool result. Loo has gone from being under/unemployed
on the family farm in nowhere-stan to working in her local third world city.
You would expect global production to be up by the production of a
third world worker, but
because globalisation swaps things around, err, well, globally, production
is up by the production of a first world worker.
How is the new wealth shared out? Loo's share is f. Americans generally get (1-f) as cheaper clothing. Jane gets her 240millionth of that,
so she is still pissed about the lost wages between being outsourced and
finding a new job.
Loo benefits from local economic development.
Americans get buffetted by economic change abroad, but long term,
they also benefit. Sometimes the Americans share of the benefits is the
largest share.
The special case
Sometimes America gets so far ahead of the competition that the terms
of trade are very much in America's favour. In the 1970's IBM could charge
what it wanted for its computers. It was a very profitable business.
But those kind of exceptional profits don't last. Other countries catch
up.
Samuelson seems to be saying that there are unusual circumstances
in which exceptional losses out way the usual benefits that America
gets from outsourcing.
If technology diffusion means that America falls back from doing wonderfully well from trade, and merely does very well from it, what kind of policy
prescription could flow from that? Erecting trade barriers to make sure
that one can never do wonderfully well from trade again in the future?
This is something that has always bothered me about
speech recognition and speech synthesis. What would it really be like to be able to chat freely to
an interface whose underlying intelligence was that of
the typical command line interpreter?
My guess is that it would be a miserable experience. The user would be seduced into attribuing a human like intelligence to the program and end up frustrated by its lack of
comprehension.
20 something years ago they had the Economist in
my school library. I was prigish and right wing.
I was pretty appalled by what I thought was a
cynical, left-wing, agit-prop kind of magazine.
Boy was I mistaken.
Sure, they have articles about
how greedy bankers are lending too much money backed by too little capital and will cause
a disaster. They have articles about corrupt
businessmen buying corrupt politicians to stop
the accounting standards body from forbidding
auditors to do non-audit work for audit clients.
They helpfully explain that auditors get bribed
with lucrative 'consulting' contracts to overlook
dodgy accounting practises. And they do this pre-Enron.
But it is the magazine of the establishment, grumbling about its members, and how they are
letting the side down. Now I love reading it.
There is a real feeling of "Ah that's how the
world really works"
I don't see the problem
Suppose I have a class name and I create a subclass place-name by adding a slot for a location. Meanwhile I need colours, both for my paints and my objects so I create a colour. Finally a create a class coloured-place-namefor named things in that are put in places and have colours, by multiple-inheritance, taking first place-name and then colour.
At this point I have an inheritance ambiguity. Obviously place-name comes first, but what next, name or colour? What I don't see is why I should care.
It is only going to matter if I have a method, act, defined for both name and colour. But how could that happen? I'm only using multiple inheritance because all three of place-name,coloured-place-name, and colour make sense. If only two of them made sense I would use single inheritance. So the meanings of act on the two classes are orthogonal, I don't want one shadowing the other.
We really have a name clash, and need to sort out our names. Perhaps act on name should be speak, and act on colour should be paint
OK the inheritance graph isn't totally ordered, but each method is only defined on a subset and, for any particular method, its subset will be totally ordered. So I cannot see a problem that actually matters in practice
Single inheritance is the one that is simple to implement. As an application programmer I want the one that is simple to use and that means not having to program around language limitations.
If you wanted to teach trigonometry using Euler's equation you would have to teach complex numbers ahead of time so that pupils would be comfortable with them.
:-)
That is probably a good idea any way. For example, turn 2+i into a right-angled triangle, two wide and one high, draw on squared paper, cut out with scissors. Do the same for 3+2i and 4+7i.
Note that (2+i)x(3+2i)=2x3+3i+4i-2=4+7i.
Place the two smaller triangles side by side to add the angles. Place on top of the big triangle and see that the angles are equal.
I think that children could grasp that there is a funny way of multiplying pairs of numbers that makes angles add up. Whether their teachers could cope with complex numbers is another matter
Maybe Common Lisp source is clean and elegant or maybe it has all the charm of porridge with finger nail clippings, but all that misses the point.
,name (,vector ,@parameter-list) ,(mapcar ,@(mapcar #'second defining-equations))))))
...) works.
Here is an example from this afternoon's coding. I'm trying to turn the Lorenz model into a musical instrument. My text book gives the differential equations as
.
x = p(y-x)
.
y = rx - xz -y
.
z = xy -bz
where p,r, and b are parameters and x,y, and z are variables, coordinates in a 3 dimensional space.
It is easy enough to code up these equations
(defun lorenz (x y z p r b)
(vector (* p (- y x))
(- (* r x)
(* x z)
y)
(- (* x y)
(* b z))))
is a function of 6 variables that returns a vector of three elements.
However that is not really what I want. I want to pass in a vector (x,y,z) with my variables bundled together. So I decide that x will be component 0, y will be component 1, and z will be component 2 and code:
(defun lorenz (v p r b)
(vector (* p (- (aref v 1)(aref v 0)))
(- (* r (aref v 0))
(* (aref v 0)(aref v 2))
(aref v 1))
(- (* (aref v 0)(aref v 1))
(* b (aref v 2)))))
Well that is crap in two different ways. First, I'm repeating myself. (aref v 0) would be OK if I only typed it once, but repetition is bad. Second, the connection to the page in my text book is lost. I really want to be copying the equation out of my text book. I can cope with infix to prefix translation, but I don't want to lose my symbolic names. Fortunately it is easy to fix
(defun lorenz (v p r b)
(let ((x (aref v 0))
(y (aref v 1))
(z (aref v 2)))
(vector (* p (- y x))
(- (* r x)
(* x z)
y)
(- (* x y)
(* b z)))))
At this point one says: the three lines with aref in them are just boiler plate, make them go away!
One wants to be able to code a function that is passed a vector, is written using component names, and returns a vector, like this
(defvecfun lorenz (p r b)
(x (* p (- y x)))
(y (- (* r x)
(* x z)
y))
(z (- (* x y)
(* b z))))
No repetition, no boiler plate, clear relationship to the equations in the book.
Common Lisp doesn't have a defvecfun command, so I add it by defining a macro
(defmacro defvecfun (name parameter-list &rest defining-equations)
(let ((vector (make-symbol "V"))
(variables (mapcar #'car defining-equations)))
`(defun
(let
(lambda (var)
(list var
(list 'aref
vector
(position var
variables))))
variables)
(vector
Now my ideal code (defvecfun lorenz (p r b)
Rather than manually translate the equations in my paper book to meet the syntax requirements of my programming language, I type the equations from the book into my source file without regard for the fact that I want x,y and z to be components of a vector. Then I write a bit of code, my macro, to automatica
For example you might want the programming course and the calculus course to be mutually supporting.
The rules for differentiation could be coded up in
the programming language. For Common Lisp it might
look like
(defparameter plus '+)
(defparameter times '*)
(defun differentiate (form variable)
(typecase form
(number 0)
(symbol (if (eql form variable) 1 0))
(list (case (first form)
(+ (list plus
(differentiate (second form) variable)
(differentiate (third form) variable)))
(* (list plus
(list times
(differentiate (second form) variable)
(third form))
(list times
(second form)
(differentiate (third form) variable))))))))
(differentiate '(* x x) 'x) => (+ (* 1 X) (* X 1))
But why are those the rules, rather than some other rules? Well it is supposed to agree with
the numerical version
(defun numerically (function argument difference)
(let ((left (funcall function (- argument difference)))
(right (funcall function (+ argument difference))))
(/ (- right left)
(* 2 difference))))
(defun square (x)(* x x))
(numerically (function square) 7 0.001) => 13.998031
And indeed
(defvar x 7)
(eval (differentiate '(* x x) 'x)) => 14
Notice the wider vision: students are taught a programming language to give them a language in which to talk about procedures, including procedures that they are expected to master in other parts of the curriculum.
If that kind of thing matters to you, you should look at Common Lisp. The built-in programmable parser is powerful enough to parse all CL programs and is configured to do so by default. Defining source-to-source transformations with DEFMACRO is an important technique
In a world of lots of little companies, competing for customers and competing for employees, we don't need job protection laws - just get a job with a rival, or start up on your own.
In that kind of 1776-world job protection laws can do more harm than good. They make it harder to get a new job, they make it harder to set up your own business.
In the real world, where job markets are dominated by a few large companies, we do need job protection laws to protect our freedom. Or maybe we need stronger competition laws to stop a small number of large companies dominating.
There is no need for the job protection laws to apply to small companies. Indeed, if job protection laws apply to big companies but not small one, that is in part a competition law, hindering the big companies in their competition with the small companies.
I've argued that telepresence will displace business air travel.
It is unreasonable to fund supersonic transport research when competition from telepresence is looming.
The idea of a patent is that the inventor gets a monopoly that he can exploit to repay the investors who backed his research.
But what happens when a product is covered by more than one patent? Every patent holder gets a veto on exploiting every-one elses' inventions!
If you propose a program of research, hoping to create a patentable invention, your bankers will want to know how many existing patents they will have to license before they can exploit your hoped for invention. Lots of patents means no funding for your research.
The patent system can only work in the way its boosters claim if there is a one patent per product rule. Let the patent office pick a single ruling patent for each product and grant the monopoly only to the inventor of the ruling patent. Then investors can back expensive research aimed at major break throughs, enticed by the prospect of having the ruling patent, and not having to buy off patent leaches.
Short copyrights protect artists from having to compete with copies of their recent work. It gives them a business model. They can give up their day job and work full time on creation. That is good for the both the artist and the public.
Long copyrights protect artists from having to compete with old public domain works. Copyright lasts so long that only very old work is in the public domain. Old stuff gets "retired" by the copyright holders, neither for sale nor in the public domain.
That is against the public interest. If artists can produce work that is better or more up to date than good, old work, then a short term of copyright provides a business model and funding. If an artist's work cannot compete with the good, old stuff, because lacks enduring merit and also lacks shiny newness it does the general public great harm to force it onto them by retiring the good, old stuff.
Surely television can be viewed:
1)from a critical point of view - Yes
2)active manner - No
Active means something like Slashdot where you get to talk back.
Now for the tricky bit. If you cannot do the active bit, will you sustain the critical bit? If you cannot call "Bullshit", you only upset yourself by watching out for it. So I doubt that one can watch TV and maintain a critical stance. Thus the answer might be that in practise it is No and No
Richard Stallman says
It started with great excitement. FORTRAN, LISP, BASIC, ALGOL, PASCAL,
PL/1, FORTH, COBOL. The economic underpinnings were clear enough, and
had three aspects:
1)The early versions of these languages left plenty of room for
improvement. That is to say, a new improved language offered cost
savings to the ultimate users of IT services.
2)The early versions of these languages were relatively simple. It
hadn't cost too much money to develop the language that far. Those
who wanted to start from scratch on a new language had to justify a
relatively modest expense to duplicate what had already been
achieved, and could point to the prospect of large savings to come
under point 1.
3)Compared to today the languages were not widely
deployed. Businessmen did not have to think in terms of duplicate
staffing, with one team skilled in the old language to maintain the
legacy code base, while another team skilled in the new language
work on duplicating the code base, and one day moving on to writing
new code that will eventually save money.
As the years rolled by languages got better. The benefits of new
computer languages were hit by diminishing returns. The threshold
cost, the money you must spend to get the new language competitive
with the old language, rose and rose. The installed base grew, and
with it the costs of change.
A theoretical solution to these problems was the programmable
programming language. Rather than start from scratch, reprogram the
old language. Under the name "extensible programming languages" this
idea had failed serveral times. Sticking points included:
1)Extension mechanism not powerful enough (C #define)
2)Extension mechanism too complicated(ALGOL68C,PROLOG)
3)Base language too simple(FORTH)
There is a three-way pull. The simpler the base language, the easier
it becomes to make a powerful extension mechanism without it becoming
too complicated.
By 1990 it was becoming clear that the CL macro system made CL into
the first fully practical programmable programming language. This
revolutionised the economics of programming language design. Compare
making a new language feature available by starting from scratch with
programming it into a programmable programming language. The advantage
of starting from scratch is that you can get the syntax "just so". If
you want the cost saving of using a programmable programming language,
you have to accept the syntax of the base language, and some mild
constraints on the syntax of your added feature. But there are
savagely diminishing returns in fiddling with syntax. That last 10% of
getting the syntax just so saves what? 1% of programming cost,
perhaps, if you are lucky and the new syntax really is an improvement.
With a programmable programming language the "new feature" is simply a
file a macro-definitions. All your legacy code still runs in the "new
language". Your programmers simply have to learn the extra bit. No
starting over.
A fully practical programmable programming language destroys the
economic rational for programming language design. The point of a
computer programming language is to save money. The point of a new
language is to save more money. There is no point in trying to save
money the expensive way, rather than the cheap way.
Very few persons have understood this. Programmers in other languages
haven't. I don't think many CL programmers have realised either. CL is
politics, not art. I think the reaction of most Lispers, to realising
that not only has Lisp won, but specifically CL has won, is to say "Oh
shit, if we had realised that we were going to be stuck with it for
all eternity, we would have done a better job of designing it."
Tough. The era of computer language design ended 13 years ago. Sorry
you missed it.
Now you are probably aware that computer language desig
A matrix multiply in Common Lisp looks like this:
(defun matrix-multiply (a b)
(assert (= (array-dimension a 1)
(array-dimension b 0)))
(let ((c (make-array (list (array-dimension a 0)
(array-dimension b 1)))))
(loop for i below (array-dimension a 0) do
(loop for j below (array-dimension b 1) do
(setf (aref c i j)
(loop for k below (array-dimension a 1)
sum (* (aref a i k)
(aref b k j))))))
c))
You are trying to tease smug lisp weenies by saying that their language is a pure functional language. That doesn't have enough truth in it to sting or to amuse.
Lisp failed in the early eighties. That is twenty years ago. Things were different back then, and it is important not to learn the wrong lessons. Here are some of the reasons LISP failed.
Virtual Memory Mysticism Four megabytes was a lot of memory back then. The junor manager could be persuaded to sign off on the purchase of a workstation with that much, but the middle manager would cut it back to two megabytes and the senior manager would cut it back to one megabyte. The fancy Lisp application would have a working set of three megabytes, so the machine would page thrash and run like cold treacle. Eventually management would be pursuaded to buy another megabyte, but it would still be too slow. The basic problem was that people treated virtual memory as magic and were reluctant to accept that there were still hard limits on the ammount of physical memory required. VLSI killed bit slice Back then, everybody and their dog was starting new mini-computer companies, using 4 AMD 2901 four bit slices to make the ALU and a 2910 to sequence the micro-code. The big Lisp vendors had their own hardware. Symbolics had Lisp machines, Xerox had D-machines. As the decade wore on, technology progressed, and VLSI CPU's such as the 68020 and 80386 slaughted the LSI CPU's. DEC's VAX was the biggest losser, but the Lisp vendors suffered greviously from mis-reading the way the hardware market was going. Naive garbage collectors Garbage collectors are hard to write. In the 80's Lisp vendors were proud that their garbage collectors were free of bugs. Unfortunately the old mark and sweep collectors tended to walk swapped out data structures, thrashing the virtual memory system. Modern generational collectors are enormously better. Computer science was young Many programmers were self taught. (I read mathematics at University.) Others had studied computer science, but were learning from academics who were new to computing themselves and thought PASCAL was a good language.Why do you want access to the AST? The idea is that you can avoid manual maintainance of repetitous code and boiler plate code by automatically generating it. Well, it is a nice idea but it is also a sophisticated idea.
Some of the application is written in the base language. Some of the application is automatically generated. The generated code doesn't appear by magic. There have to be source files, in an application specific language. There have to be code generators, written in a meta language, that take the application specific language and expand it to the base language.
It is a huge win if the meta language is transforming AST's into AST's rather than transforming text files into text files. To obtain this benefit, the programmer must be thinking in terms of the abstract syntax, rather than the surface syntax.At this point it becomes natural to give up on surface syntax and program straight to the AST. It is also natural to insist that the base language is suitable for writing AST to AST transformers, so that a separate meta language is not required. This is what Lispniks are getting at when they say that Lisp is its own meta language.
This way of thinking about programming went right over the heads of most programmers in the 80s. I think that the most important reason why Lisp failed in the early eighties is that it was 20 years ahead of its time
It would be nice to be able to run your program before you have written it. For example:
We start the program running at prompt 2, write it at prompt 3 and 5, and get the answer, 112, after 6.
This would help with one off calculations, and with refining requirements via exploratory programming. I think the issue is more of a culture/management/training thing, rather than technical difficulty.
I'm curious as to what Tyler has in mind, since Common Lisp is a strongly typed language.
Perhaps his concern is that Lisp does its type checking at run time, rather than compile time. There are two aspects to this. Some compilers, notability CMUCL, make good use of the optional declarations to do type checking at compile time and produce fast code. More importantly, the actual issue is not compile-time versus run-time, but early versus late
You always want early type checking. If your development cycle runs: edit, compile, edit, compile, run, edit,.... then you want compile time type checking. If your development cycle runs: edit, run, edit, run, compile, run,... then you want run time type checking.
Even if the software is designed top down, a Lisp programmer would code in a bottom up, test as you go, style. One window has the program source, another has the Read-Eval-Print-Loop. Immediately a function is written, it is sent to REPL and tested interpretively. Once the code is correct, it is compiled, to get full speed, and work moves to the next stage: achieving performance goals.
Thus Lisp has early type checking, and that is what is important, not whether it is compile-time or run time.
CMU Common Lisp 18d
:accessor nectar :initform (random 10))))
; flowers have nectar
; initially a random amount of nectar
(defclass flower ()
((nectar
; make a list of three flowers
(defvar flowers (loop repeat 3 collect (make-instance 'flower)))
; add an extra method to the generic function `nectar'
; for lists of flowers
(defmethod nectar ((flowers list))
(mapcar (function nectar) flowers))
; so we can see how much nectar our flowers have
(nectar flowers) => (8 9 2)
; add a setter method to the generic function
(defmethod (setf nectar) (amount (flowers list))
(dolist (bloom flowers)
(setf (nectar bloom) amount)))
; then we can set the amount of nectar in all
; the flowers in our list like this
(setf (nectar flowers) 0)
; and indeed
(nectar flowers) => (0 0 0)
Compare what the researchers want
set the nectar of all flowers to 0
with what Common Lisp has offered since 1990
(setf (nectar flowers) 0)
They should be taking advantage of existing languages, not inventing new ones.
If so, then the argument is that spam obstructs people who are trying to speak to each other. This adds to the gravity of the offence.
Some industrial waste is stable. Arsenic waste from tin mining, mercury waste from gold mining, cadmium from discarded rechargable batteries, beryllium from heat transfer uses.
None of this stuff decays at all. Waste that just goes away if you wait long enough looks good by comparison.
More significantly, there is an inverse relationship between half-life and activity. When you take out your spent fuel rods there is some U235 left, with a half-life of 700 million years, and also Strontium 90 with a half-life of 29 years. The Strontium 90 with its short half-life is releasing its energy quickly. This contributes to making the spent reactor very radio-active and very dangerous. But 290 years later 99.9% of the Strontium has decayed. Meanwhile the Uranium, which is releasing its energy too slowly to be dangerous, clouds the issue of how long reactor waste lasts. Long after the waste has ceased to be dangerous, it remains slighty radioactive.
One mind boggling point is that Uranium used as reator fuel supplies about a million times as much energy per unit weight as coal. Coal is a fairly pure product and contains only about 1.5 parts per million Uranium as a contaminant. So about 50% more Uranium goes up the chimney of a coal fired power station as goes into the reactor of a nuclear power station.
That is amusing in a way, but not very important, because the Uranium that goes into a reactor isn't dangerous anyway. The worry with nuclear power is the transmutation of Uranium into short lived, highly radioactive isotopes of other elements. However the point remains that the quantities of waste involved in nuclear power are very much smaller than the quantities involved in producing power from chemical sources.
Why do I care? I was six years old at the time of the Aberfan Disaster, the same age as many of the 116 children who died, suffocated under a slurry of waste from a coal mine after the collapse of a waste tip. The TV pictures of the time showed the gable end of the children's school. It was just like the one I attended and this upset me.
I have never forgotten that quantity is a quality of waste. The waste from the coal mine might as well have been composed of perfectly safe, inert materials. It would not have made any difference. The children were buried and suffocated because there was so much of it, not because it was "dangerous" in the sense that the word is used today.
Quantity.The governments Germany, France, and Italy have all made huge promises to their peoples of generous pensions paid out of general taxation.
The next 30 years will see the unwinding of those promises as demographic changes make them undeliverable.
What bland words for such a dire predicament! Who will innovate in the EU, knowing that their profit will be confiscated in a desperate attempt to pay the pensions bill. Will it even be possible to do business in countries riven by such social stresses? The future will be made elsewhere. The blood of the Europeans will be drunk by monsters from the past.
There you are analysing the 6 dimensional political/social space:
- socialist versus capitalist
- big business versus petit bourgeois
- factional versus collective
- collective versus individual
- homogenous versus heterogenous
- Smithian versus Ricardian
contemplating the 3.7 dimensional submanifold of the chaotic attractor.Knowledge of the dynamics lets you predict several orbits in advance that the system is going to visit an undesirable region of the attractor. No worries. Even a tiny intervention will blossom exponentially. Knowing the dynamics you can exploit the sensitivity of trajectories on the attractor in order to intervene cheaply and inconspicuously.
But is that the only option? Adjusting the parameters of the dynamics will move the attractor. Events that were likely become deterministically impossible. Events that were deterministically impossible become likely.
What would a parameter adjustment look like? The oral contraceptive is an example. Fertility is a key parameter of society, and oral contraception makes a huge difference to the coupling constant between social pressures and individual desires for fertility and actual outcomes.
I don't have a clue how to construct a Hari Seldon style psycho-history, but that is because I'm stupid. Chaos in dynamical systems is not the problem.
Here is how globalisation usually works:
Loo, Foo, and Poo work in the farm in Vietnam or Bangaladesh or somewhere. It is a small farm and only really needs two to work it, so Loo goes to the big city, learns to operate a sewing machine and gets a job in a garment factory at a fraction f of American wages.
In USA Jane's job in the garment factory is out-sourced, so she has to learn to do something just as boring with pipetts, and get a machine minders job with a bio-tech company. Jane is out $10000 in lost wages before she gets her new job so she is pissed
Short term outsourcing sucks, but who are the winners and losers long term? Well the garments are still getting made, and Jane is doing a real American job that wasn't getting done before, so the world economy is up by the production of an American worker.
That is a pretty cool result. Loo has gone from being under/unemployed on the family farm in nowhere-stan to working in her local third world city. You would expect global production to be up by the production of a third world worker, but because globalisation swaps things around, err, well, globally, production is up by the production of a first world worker.
How is the new wealth shared out? Loo's share is f. Americans generally get (1-f) as cheaper clothing. Jane gets her 240millionth of that, so she is still pissed about the lost wages between being outsourced and finding a new job.
Loo benefits from local economic development. Americans get buffetted by economic change abroad, but long term, they also benefit. Sometimes the Americans share of the benefits is the largest share.
The special case
Sometimes America gets so far ahead of the competition that the terms of trade are very much in America's favour. In the 1970's IBM could charge what it wanted for its computers. It was a very profitable business. But those kind of exceptional profits don't last. Other countries catch up.
Samuelson seems to be saying that there are unusual circumstances in which exceptional losses out way the usual benefits that America gets from outsourcing. If technology diffusion means that America falls back from doing wonderfully well from trade, and merely does very well from it, what kind of policy prescription could flow from that? Erecting trade barriers to make sure that one can never do wonderfully well from trade again in the future?
This is something that has always bothered me about speech recognition and speech synthesis. What would it really be like to be able to chat freely to an interface whose underlying intelligence was that of the typical command line interpreter?
My guess is that it would be a miserable experience. The user would be seduced into attribuing a human like intelligence to the program and end up frustrated by its lack of comprehension.
20 something years ago they had the Economist in my school library. I was prigish and right wing. I was pretty appalled by what I thought was a cynical, left-wing, agit-prop kind of magazine.
Boy was I mistaken.
Sure, they have articles about how greedy bankers are lending too much money backed by too little capital and will cause a disaster. They have articles about corrupt businessmen buying corrupt politicians to stop the accounting standards body from forbidding auditors to do non-audit work for audit clients. They helpfully explain that auditors get bribed with lucrative 'consulting' contracts to overlook dodgy accounting practises. And they do this pre-Enron.
But it is the magazine of the establishment, grumbling about its members, and how they are letting the side down. Now I love reading it. There is a real feeling of "Ah that's how the world really works"