Strangest language feature
stackoverflow.com
stackoverflow.com
Here are a couple, to get things rolling.
Pattern matching. This is a favorite of mine - stating what you want (or expect), possibly with variables, and letting the language generate the tree of if/case statements. I find pattern-matching code extremely easy to read, easy to extend, almost always right the first time, etc. It works with both static (ML-style variant types, reminding you to check exhaustively) and dynamic (Erlang-style, "handle what you can or throw an exception") typing. awk is based around a weaker form of pattern matching (only matching against ints and regexes, rather than whole trees), and it's still great for quick hacks. PM seems to mesh poorly with conventional OO, though.
Compile-time metaprogramming. This is HN, you've probably heard plenty about Lisp macros, so I'll leave it at that.
Incremental development / hot code loading. Erlang has this (with soft real-time guarantees), Lisp, Smalltalk, and basically anything image-based has had this for ages. It's often easier to grow a system piece by piece than to build it upfront and plug in together afterward.
Iterators/generators. Without needing a fully lazy-by-default language such as Haskell, it's often handy to have a handle into a (possibly infinite) stream that you can pull from as necessary. Prolog combines pattern matching (unification really, a step beyond pattern matching) with backtracking, so you can write "generate and test" code: "here's what I want, this generates a stream of all possible candidates, here's how to narrow it down". It's sometimes too slow for use in production (due to combinatorial blowups), but it's excellent for prototyping, and can usually be made good enough with some tweaks.
Coroutines and actors. Like iterators and generators, but breaking the flow of execution into lots of little autonomous pieces. Communication makes dataflow explicit, most things can be easily understood in isolation, and they can often be run in parallel. (Coroutines are cooperative.)
First Class Continuations like in Scheme.
* But I've heard it's really not implemented for performance, and probably doesn't get used that much. I'm not really into Ruby, so...anyone?
Of course, you can do CPS yourself, though realistically you need first-class functions, tail-call optimization, and garbage collection or the extra bookkeeping will make it overwhelmingly complicated.
assert( ( o-------------o
|L \
| L \
| L \
| o-------------o
| ! !
! ! !
o | !
L | !
L | !
L| !
o-------------o ).volume == ( o-------------o
| !
! !
! !
o-------------o ).area * int(I-------------I) );
http://stackoverflow.com/questions/1995113/strangest-languag...From what I've seen, APL is pretty much a write-only language. Code can't be read, only deciphered.
It's depressing how the computing world is overrun with majoritarian prejudice. Even here. I suppose it's just human nature, but an open mind is so rare.
But I was motivated to do all of that because of people I respected who said "This contains some genuinely new ideas worth learning." So far, I haven't heard anyone say that about APL, and so I guess I assumed that either its differentiation was only in a hyper-terse syntax, or that it was not generally suitable for a generalized programming language (similar to regex).
If that's an invalid assumption, then please point me towards an article elucidating what's great about APL, and I'll read it sincerely.
I was just curious because it was so different, but the thing that really convinced me was going through some of the J "labs" (a bunch of math lessons included with J, that incidentally teach it along the way) and spending a couple hours picking apart this code (http://nsl.com/papers/origins.htm) to get into the APL frame of mind.
I would suggest not getting too hung up on the syntax, and instead focusing on the pros and cons of doing everything over collections by default, with implicit looping. "Thinking big", as Henry Rich calls it in _J for C Programmers_ (also a good resource). The ideogram-based syntax is an historical thing, and getting fixated on that is like thinking the only novel thing about Lisp is all the parens.
See also: "The World's Most Mind-Bending Language Has the Best Development Environment" (http://prog21.dadgum.com/48.html)
Here's a good intro, by Arthur Whitney himself: http://www.vector.org.uk/archive/v101/whitney101_74.htm
That's right, it's a language that makes more sense backwards than it does forwards.
Also, I can't read Bosnian, but that says more about me than Bosnian. It doesn't make it a "write-only language".
On the other hand, the fact that the Chinese have put their language through several reforms because of systematic problems with literacy and reading comprehension does show that, on a continuum between "readable" and "write-only", the Chinese language leans more toward the latter.
The parallels to actual human languages also break down here - reading APL is intimidating like reading Chinese, but it also has less than a hundred symbols (fifty-ish, IIRC), so it's really not comparabl in terms of "systematic problems with literacy and reading comprehension". I think the APL-languages are more like vi. Do vi(m) users think "9kdd2jp"? In writing, it looks like noise.
At risk of being slighty Euro-centric, in fact, from what little I know, western literature and tradition seems to have more emphasis on semantic content and the conveyance of literal ideas than does most Chinese.
* Joy also does this, but seems much less practical.
Chinese is also not a great comparison, because the vocabulary is so large. I originally said Turkish, then Bosnian, but changed it to Chinese because the "page with a grid of Chinese characters" is probably how most people think APL looks.
I learned a bit of Haskell on project euler, and when you solve a level you get to see the other solutions; the APL ones just blew my mind. What a strange little language.
sub foo {my $x='fish'; local $y='chips'; &bar;}
sub bar {print "\$x is >$x< and \$y is >$y<\n";}
This will output $x is >< and $y is >chips<
It's quite handy - saves passing around a "context" object, for example. The remarkable thing is how few languages implement some form of it.I think you mean it's the only widely used variant where it's the default. It's available in CL and Clojure when you want (need?) it.
import Control.Monad.Reader
type Action = ReaderT String IO ()
foo :: Action
foo = do
bar
local (const "new state") bar
bar
bar :: Action
bar = liftIO . putStrLn =<< ask
> runReaderT foo "foo"
foo
new state
fooIIRC common lisp supports dynamic scoping too -- it defaults to lexical scoping though.
sub greet {
local ($who) = @_;
print "hello, $who\n";
}
$who = "world";
&greet($who);
This would print, "hello, " with a newline, due to a design bug called "variable suicide", which has been fixed in newer Perls.Needless to say, this made the extract-subroutine refactoring quite a bit more trouble in Perl 4.
sub foo {
local $ENV{HOME} = "/foo/bar";
Code::I::Don't::Own();
}
foo();
Having dynamic scope here ensures that the foreign code will use the environment I want without me having to alter it.Here is another example where dynamic scoping can indeed be very useful:
sub bar { 'bar' }
sub baz { bar() }
sub foo {
no warnings 'redefine';
local *bar = sub { 'My Bar' };
baz();
}
say foo(); # => 'My Bar'
say baz(); # => 'bar'I always found the type system of PHP questionable, especially the useless and bug provoking unity between arrays and hash tables. However, ECMAScript provides such mis-design at an even lower level of the language. Nevertheless, I still like working with ECMAScript because at least it has proper closures.
> A tick is an event that occurs for every N low-level tickable statements executed by the parser within the declare block. The value for N is specified using ticks=N within the declare blocks's directive section.
( http://www.php.net/manual/en/control-structures.declare.php )
PHP is a hodgepodge of inconsistent APIs and general weirdness already, but I really did sit back and have a good WTF moment when I discovered this 'feature'. I have yet to encounter many people who have ever heard of ticks, let alone anyone who has actually implement functionality that depended on them. I've never seen something like that in Python or Ruby.
I made a simple profiler by setting the hook to run every X ticks (typically 10,000), recording the call stack, and then seeing where most of the execution happens. If every other time you look at the vm, it's in the same place, then it's clearly a hotspot.
I don't know of an equivalent in Python or Ruby, off the top of my head, but I'd be surprised if they weren't available.
Another fun one is that in Perl that local can operate on data structures. As in local $foo{bar}. (I use this every so often in recursion sanity checks. But it is still an odd feature.)
These let you use the "WTF operator":
(foo() != ERROR)??!??! cerr << "Error occurred" << endl;It ought not to compile though, since it's trying to shift cerr by a string!
>>> x=5
>>> 1<x<10
True
>>> 1<x<3
False
EDIT: fixed spaces, thanks epochwolf for the indent tip. >>> x=5
>>> 1<x<10
True
>>> 1<x<3
False
(Indent 4 spaces to show code)i think in the OA they were mostly talking about bad-strange.
$ perl -E 'say lc (@a="a".."asdf")'
30530Mathematica, which has much in common with lisp, does something analogous to (inequalities a '<= b '< c), using symbols for the comparisons.
1. The flip-flop
>> s = true
>> (1..10).reject { true if (s = !s) .. (s) }
=> [1, 3, 5, 7, 9]
2. A snake in my Ruby?!? # Works in both Python and Ruby
print """Hello World"""
3. END vs at_exit END {
puts "Ruby has END ..."
}
at_exit do
puts "... and at_exit"
end
puts "Do you know the difference?"
4. BEGIN/END wtf? # Have you ever seen these in production code?
BEGIN {}
END {}
5. The wonders of a single space # Returns the position where the regexp matches "foobar",
# or nil if no match.
def get(regexp = /bar/)
regexp =~ "foobar"
end
get /1#/ # => nil
get / 1#/ # => 3 <- WTF?
6. Local variable tables; don't we all love them? def get(regexp = /bar/)
regexp =~ "foobar"
end
get /1#/ # => nil
get = 5
get /1#/ # => 5
get / 1#/ # => 5 cat /usr/share/dict/words | ruby -lne 'puts $_.reverse; n = (n || 0) + 1; END{ puts "total: #{ n }" }' [1,2,3].each{|n| puts n }
versus [1,2,3].each do |n|
m = n + 1
puts m
end
The reason? do/end is much prettier than {}, but {} is really nice for chaining... [1,3,2].collect{|n| n + 2 }.sortFlip-flops. Do I need to elaborate?
# parse mail messages
while (<$email>) {
$in_header = 1 .. /^$/;
$in_body = /^$/ .. eof;
if ($in_header) {
# do something
} else { # in body
# do something else
}
}
And other examples at http://perldoc.perl.org/perlop.html#Range-Operators