1. Somebody's going to write an "Imagine a Beowulf cluster of these!" comment. This will not really get modded up much
2. Somebody's going to make an utterly offtopic and mildly racist joke about the dumb Indian IT workers who speak really bad English and take jobs away from smart geeks. This will of course shoot right up to (+5, Funny).
In Ruby, the most common way to create a class is to use a class... end block, but you can also do it in a more OOP way by using a class method of Class:
MyClass = Class.new do # class-scope definitions end
This is just a call the new method of class Class; it creates the class, executes all the statements in the block within the scope of the class, and assigns the Class object to the constant MyClass.
It is also possible to subclass Class to make your own kinds of classes; the Class class provides a inherited hook to catch when somebody inherits from it, and its superclass Module has a method_added hook.
I'm not sure what kind of behavior you want to overload the normal Python class and def statements to do, but I suspect you have multiple workarounds to do what you want in Ruby. Two ideas:
Don't use the class statement; subclass Class to MyClass, implement the behavior you want, and create classes of your new kind by calling MyClass.new with a block. Then you instantiate them normally.
Create MyBehavior as a plain old vanilla class (or maybe as a mixin module, haven't thought it through) which implements the behavior you want. The classes with the behavior you want should subclass MyBehavior (or if you use a mixin, declare include MyBehavior at the top).
As to how to modify the behavior of methods, look at the ExampleDate.once method in this chapter of Programming Ruby (search for "Tadayoshi Funaba"), for an example of Ruby code that modifies the behavior of a method (by renaming it and replacing it with a wrapper). In this example it needs to be requested explicitly, but a class can intercept method creation and do this sort of thing automatically for all methods.
Where is a language with the power of Lisp and the ease of Python?
Ruby isn't that language, but it's close enough that you ought to look at it. Code blocks allow an amount of syntactic extensibility that's much smaller than Lisp, but still quite useful.
Only system designers can. That's the fundamental mistake in that quote. A metaphor is something the designer uses to make the interface easier for the user to learn, not something the user must slavishly adhere to if they use the interface.
Wow, what a strange way to evaluate functions that take more than one argument.
You're thinking wrong about it-- conceptually, all functions take a single argument. Well, ok, you can get away with thinking of functions as having multiple arguments most of the time; but the point of the design is that you can apply functions partially:
# let f x y = x + y;; val f : int -> int -> int = <fun> # let add1 = f 1;; (* equivalent to let add1 y = 1 + y *) val add1 : int -> int = <fun> # add1 3;; - : int = 4
I guess that would partially explain why it isn't notated compose(square, cos), because although that's the net effect it isn't actually evaluated that way.
A further confusion is that it's possible to write functions like this:
# let g (x,y) = x + y;; val g : int * int -> int = <fun> # g (2,3);; - : int = 5
The thing is that (2,3) is a single value-- a tuple of two ints (int * int)-- and g is a function from tuples of ints to ints. Tuples don't support partial evaluation like curried functions, but you can pattern match over their contents...
Pullum utterly misses the point of the research reported by the article, which he should have been able to reconstruct:
Don't get me wrong: it's not that I have any objection at all to scientific results on whether dogs can remember enough of a correlation between human speech sounds and specific toys to go fetch the right one in response to the right word, which is what we are talking about in the case of this story.
But that's not all that the story is talking about-- the exclusion learning bit is really important. Pullum fails to catch it, and thus misreports the research as being purely about sound/object association.
I think the PDA makers have been very dumb not to go agressively for the under-$100 category. The Palm Zire 21 is the only current model there, and quality control has been horrible.
If somebody would make a reliable, mono screen PalmOS PDA with decent memory, better input than cell phones and good connectivity through an affordable companion cellphone model, it would sell if marketed right.
Function application associates to the left, period.
The O'Caml example can be improved with pattern guards (ecode is eating my indentation):
let rec member x btree = match btree with Empty -> false | Node (y, left, right) when x = y -> true | Node (y, left, right) when x < y -> member x left | _ -> member x right
Two important things you don't mention are: (a) Python doesn't actually have a case statement; (b) O'Caml's match... with isn't strictly equivalent to the case statement from most languages: O'Caml's is more powerful, since it matches arbitrarily complex patterns to complex values, binds the variables in the pattern to the matching parts in the result expression (kind of like how a regexp match assigns parenthesized subexpressions to $1, $2, etc. in perl-style regexps).
$ sml Standard ML of New Jersey v110.42 [FLINT v1.5], October 16, 2002 - 1 + 1; (* Add two ints *) val it = 2 : int - 1.0 + 1.0; (* Add two floats *) val it = 2.0 : real - 1 + 1.0; (* Error! *) stdIn:5.1-5.8 Error: operator and operand don't agree [literal] operator domain: int * int operand: int * real in expression: 1 + 1.0 uncaught exception Error raised at:../compiler/TopLevel/interact/evalloop.sml:52.48-5 2.56 ../compiler/TopLevel/interact/evalloop.sml:35.55
- fun f x y = x + y; (* Define a function *) val f = fn : int -> int -> int - fun f x y = f (x-1) y; (* Define a recursive function *) val f = fn : int -> 'a -> 'b
I had a look at Dylan, and I concluded that I would never choose it over Common Lisp. It's really Lisp with a more conventional (and verbose) syntax.
I'd go for O'Caml family-- it's more different to the languages that you probably know already. Take a look at Standard ML too-- if you know O'Caml, SML differs mainly in the syntax and libraries, and there's more books (at least in English) for SML, whose code translates trivially to O'Caml.
Why the hell should number of lines be more important than number of bytes? After all in C you can type everything on a line and Python makes you have the need to have identation.
You need to assume that the programs are written in a readable style. You could put all your C code in one line, yes-- but who would really do that? It's really a pathological case that should be ignored.
Of course, there are still some possible sources of discrepancies-- a C programmer who puts their opening brackets in a line by themselves will generate more lines than one who puts them at the end of lines. Likewise, Python doesn't have end-of-block tokens, which means that blocks in Python often have one line less than the equivalent in other languages.
Lines of code is a better measure than bytes of source because (a) it's blind to differences in identifier length (like the ones that motivated the criticism of the Java vs. C# comparison in this thread); (b) a language which requires fewer lines packs more functionality in each screenful of code, which might make a program easier to understand without jumping back and forth.
Perhaps another way of putting it: number of bytes might be a better measure of how much you need to type, but number of lines is probably a good measure of how much code you need to read. And I think the second is more important.
The measure that the comparison is applying is the size of the source code in bytes. If we're talking about the size of the executable, (e.g. bytecode in Java, C# or Python), bytes is the natural measure.
Haskell is nifty, but I can't see myself using a language with absolute functional purity and pervasive laziness. I think the ML approach is better-- it's functional by default, but allows "functions" with side effects and explicit reference values. And while ML is strict, nearly all implementations include features for lazy evaluation.
In my mind the killer features in Haskell are the type classes and the "functors" (in quotes because the word means something very different in ML and Haskell). It would be really cool to have an ML variant with those.
I can't understand why this person took in Haskell and OCaml anyway*
The comparison is being hosted under the pages for merd, a language which aims to be kind of a hybrid of Ruby and ML/Haskell.
* I'm not even going to bother wondering about C# and Java.
I think they are control cases.
And it made a good impression in one of my job applications, where the contact person knows it pretty well. It won't impress most people, sure, but (a) people who don't know Ruby will understand that means you could do Python, PHP or Perl; (b) people who do know Ruby will think better of you.
The study is clearly aimed at arguing that the process psycholinguists call lexical access (which laypeople would probably call "remembering words") does not require innate structure specific to the human species.
In fact, if you know just a bit about contemporary research in child language you can pick up the hints in the AP article Pullum links about how it ties in:
The dog seemingly understood that because he knew the names of all the other toys, the new one must be the one with the unfamiliar name. "Apparently he was able to link the novel word to the novel item based on exclusion learning, either because he knew that the familiar items already had names or because they were not novel," said the researchers, led by Julia Fischer of the Max Planck Institute for Evolutionary Anthropology in Leipzig.
This is reminiscent of some of the work of Eve Clark-- which Geoff can't be excused not to know.
By passing 10 things, their job is easy. That's all they see. They don't know about registers (other than they exist and are sorta like variables on the CPU). So they don't know that to pass 10 things you might put some in registers but the rest will have to be passed in memory (which is slow) as opposed to puting everything in registers (if at all possible) which is faster (especially for simple functions).
Passing 10 argument is bad regardless of the performance issues. These students are making a much more fundamental mistake: they're not dividing up the problem properly into easy-to-understand pieces.
A useful analogy (but don't take it too literally cause I'm oversimplifying it): verbs in natural languages never have more than 3 arguments (subject, direct object, indirect object). If you find yourself crassly exceeding this, you need a justification.
If you really believe in personal freedoms - you gotta side with Bush on this one. Companies ought to be able to do what they please within the law. [my emphasis]
Personal freedoms for companies? Sorry, you mean free trade.
(Yes, I'm aware that corporations are "legal persons" in the USA. But that's a contingent legal fact.)
My laptop is a P2-300 with 288MB of RAM, and XP is perfectly usable. The commit charge hardly ever goes over 200MB. Of course I'm not doing any major crunching: my major apps are Firefox and XEmacs.
How is the composition of a digital photograph different from the composition of a film photograph?
Duh, that's the point.
Or a watercolor, for that matter?
That's a hard question. At one level, both involve the placement of lines and shapes on a plane. At another... the photographer works within a set of constraints very different from the painter-- film records a real-world scene more or less mechanically, so perspective and crop must be controlled by a combination of camera placement and lens focal length, which are subject to all sorts of mechanical constraints too.
The painter can do all sorts of stuff that the photographer can't-- hell, the painter can dispense with perspective altogether if he so wishes.
2. Somebody's going to make an utterly offtopic and mildly racist joke about the dumb Indian IT workers who speak really bad English and take jobs away from smart geeks. This will of course shoot right up to (+5, Funny).
It is also possible to subclass Class to make your own kinds of classes; the Class class provides a inherited hook to catch when somebody inherits from it, and its superclass Module has a method_added hook.
I'm not sure what kind of behavior you want to overload the normal Python class and def statements to do, but I suspect you have multiple workarounds to do what you want in Ruby. Two ideas:
- Don't use the class statement; subclass Class to MyClass, implement the behavior you want, and create classes of your new kind by calling MyClass.new with a block. Then you instantiate them normally.
- Create MyBehavior as a plain old vanilla class (or maybe as a mixin module, haven't thought it through) which implements the behavior you want. The classes with the behavior you want should subclass MyBehavior (or if you use a mixin, declare include MyBehavior at the top).
As to how to modify the behavior of methods, look at the ExampleDate.once method in this chapter of Programming Ruby (search for "Tadayoshi Funaba"), for an example of Ruby code that modifies the behavior of a method (by renaming it and replacing it with a wrapper). In this example it needs to be requested explicitly, but a class can intercept method creation and do this sort of thing automatically for all methods.Ruby isn't that language, but it's close enough that you ought to look at it. Code blocks allow an amount of syntactic extensibility that's much smaller than Lisp, but still quite useful.
Only system designers can. That's the fundamental mistake in that quote. A metaphor is something the designer uses to make the interface easier for the user to learn, not something the user must slavishly adhere to if they use the interface.
You're thinking wrong about it-- conceptually, all functions take a single argument. Well, ok, you can get away with thinking of functions as having multiple arguments most of the time; but the point of the design is that you can apply functions partially:
I guess that would partially explain why it isn't notated compose(square, cos), because although that's the net effect it isn't actually evaluated that way.A further confusion is that it's possible to write functions like this:
The thing is that (2,3) is a single value-- a tuple of two ints (int * int)-- and g is a function from tuples of ints to ints. Tuples don't support partial evaluation like curried functions, but you can pattern match over their contents...No.
All that Pullum is saying is that the dog isn't understanding language*, and so the phrase is misused in the article.
Pullum doesn't see the positive things about the article. Overall, I thought it was slightly better than average reporting.
I think the PDA makers have been very dumb not to go agressively for the under-$100 category. The Palm Zire 21 is the only current model there, and quality control has been horrible. If somebody would make a reliable, mono screen PalmOS PDA with decent memory, better input than cell phones and good connectivity through an affordable companion cellphone model, it would sell if marketed right.
The O'Caml example can be improved with pattern guards (ecode is eating my indentation):
Two important things you don't mention are: (a) Python doesn't actually have a case statement; (b) O'Caml's match$ sml ../compiler/TopLevel/interact/evalloop.sml:52.48-5 2.56
../compiler/TopLevel/interact/evalloop.sml:35.55
Standard ML of New Jersey v110.42 [FLINT v1.5], October 16, 2002
- 1 + 1; (* Add two ints *)
val it = 2 : int
- 1.0 + 1.0; (* Add two floats *)
val it = 2.0 : real
- 1 + 1.0; (* Error! *)
stdIn:5.1-5.8 Error: operator and operand don't agree [literal]
operator domain: int * int
operand: int * real
in expression:
1 + 1.0
uncaught exception Error
raised at:
- fun f x y = x + y; (* Define a function *)
val f = fn : int -> int -> int
- fun f x y = f (x-1) y; (* Define a recursive function *)
val f = fn : int -> 'a -> 'b
I had a look at Dylan, and I concluded that I would never choose it over Common Lisp. It's really Lisp with a more conventional (and verbose) syntax. I'd go for O'Caml family-- it's more different to the languages that you probably know already. Take a look at Standard ML too-- if you know O'Caml, SML differs mainly in the syntax and libraries, and there's more books (at least in English) for SML, whose code translates trivially to O'Caml.
You need to assume that the programs are written in a readable style. You could put all your C code in one line, yes-- but who would really do that? It's really a pathological case that should be ignored.
Of course, there are still some possible sources of discrepancies-- a C programmer who puts their opening brackets in a line by themselves will generate more lines than one who puts them at the end of lines. Likewise, Python doesn't have end-of-block tokens, which means that blocks in Python often have one line less than the equivalent in other languages.
Lines of code is a better measure than bytes of source because (a) it's blind to differences in identifier length (like the ones that motivated the criticism of the Java vs. C# comparison in this thread); (b) a language which requires fewer lines packs more functionality in each screenful of code, which might make a program easier to understand without jumping back and forth. Perhaps another way of putting it: number of bytes might be a better measure of how much you need to type, but number of lines is probably a good measure of how much code you need to read. And I think the second is more important.
The measure that the comparison is applying is the size of the source code in bytes. If we're talking about the size of the executable, (e.g. bytecode in Java, C# or Python), bytes is the natural measure.
So perl regexps are cryptic and hard to read even if you know regexps already. Thank you.
$str =~ /(.*?)\&(\w+)\((.*?)\)/gis
You can certainly have .* or .?, but .*? is surely ill-formed.
In my mind the killer features in Haskell are the type classes and the "functors" (in quotes because the word means something very different in ML and Haskell). It would be really cool to have an ML variant with those.
I can't understand why this person took in Haskell and OCaml anyway* The comparison is being hosted under the pages for merd, a language which aims to be kind of a hybrid of Ruby and ML/Haskell. * I'm not even going to bother wondering about C# and Java. I think they are control cases.
Measuring program size in bytes is stupid. Lines of code, though still rife with problems, is a much better measure.
And it made a good impression in one of my job applications, where the contact person knows it pretty well. It won't impress most people, sure, but (a) people who don't know Ruby will understand that means you could do Python, PHP or Perl; (b) people who do know Ruby will think better of you.
In fact, if you know just a bit about contemporary research in child language you can pick up the hints in the AP article Pullum links about how it ties in:
This is reminiscent of some of the work of Eve Clark-- which Geoff can't be excused not to know.Passing 10 argument is bad regardless of the performance issues. These students are making a much more fundamental mistake: they're not dividing up the problem properly into easy-to-understand pieces.
A useful analogy (but don't take it too literally cause I'm oversimplifying it): verbs in natural languages never have more than 3 arguments (subject, direct object, indirect object). If you find yourself crassly exceeding this, you need a justification.
If you really believe in personal freedoms - you gotta side with Bush on this one. Companies ought to be able to do what they please within the law. [my emphasis] Personal freedoms for companies? Sorry, you mean free trade. (Yes, I'm aware that corporations are "legal persons" in the USA. But that's a contingent legal fact.)
My laptop is a P2-300 with 288MB of RAM, and XP is perfectly usable. The commit charge hardly ever goes over 200MB. Of course I'm not doing any major crunching: my major apps are Firefox and XEmacs.
Duh, that's the point.
Or a watercolor, for that matter? That's a hard question. At one level, both involve the placement of lines and shapes on a plane. At another... the photographer works within a set of constraints very different from the painter-- film records a real-world scene more or less mechanically, so perspective and crop must be controlled by a combination of camera placement and lens focal length, which are subject to all sorts of mechanical constraints too.
The painter can do all sorts of stuff that the photographer can't-- hell, the painter can dispense with perspective altogether if he so wishes.
You have pretty much the same setup as I do. Don't tell me you shoot Astia too!