From: Jonathan Gardner on 1 Feb 2010 17:28 On Jan 31, 3:01 am, rantingrick <rantingr...(a)gmail.com> wrote: > On Jan 30, 10:43 am, Nobody <nob...(a)nowhere.com> wrote: > > > That's also true for most functional languages, e.g. Haskell and ML, as > > well as e.g. Tcl and most shells. Why require "f(x)" or "(f x)" if "f x" > > will suffice? > > yuck! wrapping the arg list with parenthesis (python way) makes the > most sense. Its to easy to misread somthing like this > > onetwothree four five six > > onetwothree(four, five, six) #ahhh... plain english. In Lisp-ish languages, you have a list of stuff that represents a function call: (a b c d) means: Call "a" with values (b, c, d) While this certainly doesn't agree with what you learned in Algebra, it is a reasonable syntax that exposes the code-data duality of programs. There is, however, one fatal flaw. Why is the first element so different than the rest? This is inconsistent with what people who are unfamiliar with the language would expect. Indeed, in teaching Lisp, learners have to be reminded about how the evaluator looks at lists and processes them. I would expect a clear, simple language to have exactly one way to call a function. This calling notation would clearly distinguish between the function and its parameters. There are quite a few options, and it turns out that "function(arg, arg, arg)" is a really good compromise. One of the bad things with languages like perl and Ruby that call without parentheses is that getting a function ref is not obvious. You need even more syntax to do so. In perl: foo(); # Call 'foo' with no args. $bar = foo; # Call 'foo; with no args, assign to '$bar' $bar = &foo; # Don't call 'foo', but assign a pointer to it to '$bar' # By the way, this '&' is not the bitwise-and '&'!!!! $bar->() # Call whatever '$bar' is pointing at with no args Compare with python: foo() # Call 'foo' with no args. bar = foo() # 'bar' is now pointing to whatever 'foo()' returned bar = foo # 'bar' is now pointing to the same thing 'foo' points to bar() # Call 'bar' with no args One is simple, consistent, and easy to explain. The other one requires the introduction of advanced syntax and an entirely new syntax to make function calls with references. Note that the Algebra notation of functions allows for an obvious, simple way to refer to functions without calling them, leading to syntax such as "f o g (x)" and more.
From: Jonathan Gardner on 1 Feb 2010 17:35 On Jan 31, 12:43 pm, Nobody <nob...(a)nowhere.com> wrote: > > If it was common-place to use Curried functions and partial application in > Python, you'd probably prefer "f a b c" to "f(a)(b)(c)" as well. > That's just the point. It isn't common to play with curried functions or monads or anything like that in computer science today. Yes, Haskell exists, and is a great experiment in how such a language could actually work. But at the same time, you have to have a brain the size of the titanic to contain all the little details about the language before you could write any large-scale application. Meanwhile, Python's syntax and language is simple and clean, and provides tremendous expressiveness without getting in the way of the programmer. Comparing Python's syntax to Haskell's syntax, Python is simpler. Comparing what Python can do to what Haskell can do, Haskell is much faster at certain tasks and allows the expression of certain things that are difficult to express in Python. But at the end of the day, the difference really doesn't matter that much. Now, compare Python versus Language X along the same lines, and the end result is that (a) Python is extraordinarily more simple than Langauge X, and (b) Python is comparable in expressiveness to Language X. That's the #1 reason why I like Python, and why saying Ruby and Python are similar isn't correct.
From: Chris Rebert on 1 Feb 2010 18:07 On Mon, Feb 1, 2010 at 2:28 PM, Jonathan Gardner <jgardner(a)jonathangardner.net> wrote: > On Jan 31, 3:01 am, rantingrick <rantingr...(a)gmail.com> wrote: >> On Jan 30, 10:43 am, Nobody <nob...(a)nowhere.com> wrote: >> > That's also true for most functional languages, e.g. Haskell and ML, as >> > well as e.g. Tcl and most shells. Why require "f(x)" or "(f x)" if "f x" >> > will suffice? >> >> yuck! wrapping the arg list with parenthesis (python way) makes the >> most sense. Its to easy to misread somthing like this >> >> onetwothree four five six >> >> onetwothree(four, five, six) #ahhh... plain english. > > In Lisp-ish languages, you have a list of stuff that represents a > function call: > >  (a b c d) > > means: Call "a" with values (b, c, d) > > While this certainly doesn't agree with what you learned in Algebra, > it is a reasonable syntax that exposes the code-data duality of > programs. There is, however, one fatal flaw. Why is the first element > so different than the rest? This is inconsistent with what people who > are unfamiliar with the language would expect. Indeed, in teaching > Lisp, learners have to be reminded about how the evaluator looks at > lists and processes them. > > I would expect a clear, simple language to have exactly one way to > call a function. This calling notation would clearly distinguish > between the function and its parameters. There are quite a few > options, and it turns out that "function(arg, arg, arg)" is a really > good compromise. > > One of the bad things with languages like perl and Ruby that call > without parentheses is that getting a function ref is not obvious. You > need even more syntax to do so. In perl: > >  foo();    # Call 'foo' with no args. >  $bar = foo;  # Call 'foo; with no args, assign to '$bar' >  $bar = &foo; # Don't call 'foo', but assign a pointer to it to '$bar' >        # By the way, this '&' is not the bitwise-and '&'!!!! >  $bar->()   # Call whatever '$bar' is pointing at with no args > > Compare with python: > >  foo()    # Call 'foo' with no args. >  bar = foo() # 'bar' is now pointing to whatever 'foo()' returned >  bar = foo  # 'bar' is now pointing to the same thing 'foo' points to >  bar()    # Call 'bar' with no args > > One is simple, consistent, and easy to explain. The other one requires > the introduction of advanced syntax and an entirely new syntax to make > function calls with references. Ruby isn't nearly as bad as Perl in this regard; at least it doesn't introduce extra syntax (though there are extra method calls): foo # Call 'foo' with no args. bar = foo # Call 'foo; with no args, assign to bar bar = method(:foo) # 'bar' is now referencing the 'foo' "function" bar.call # Call 'bar' (i.e. 'foo') with no args Cheers, Chris -- http://blog.rebertia.com
From: Paul Rubin on 1 Feb 2010 18:08 Jonathan Gardner <jgardner(a)jonathangardner.net> writes: > I judge a language's simplicity by how long it takes to explain the > complete language. That is, what minimal set of documentation do you > need to describe all of the language? With a handful of statements, > and a very short list of operators, Python beats out every language in > the Algol family that I know of. Python may have been like that in the 1.5 era. By now it's more complex, and not all that well documented. Consider the different subclassing rules for new and old style classes, the interaction of metaclasses and multiple inheritance, the vagaries of what operations are thread-safe without locks, the inter-thread signalling mechanism that can only be invoked through the C API, the mysteries of generator-based coroutines, etc. I've never used Ruby and I think its syntax is ugly, but everyone tells me it's more uniform. Simplicity is not necessarily such a good thing anyway. Consider FORTH.
From: Nobody on 1 Feb 2010 21:03
On Sun, 31 Jan 2010 22:36:32 +0000, Steven D'Aprano wrote: >> for example, in if you have a function 'f' which takes two parameters to >> call the function and get the result you use: >> >> f 2 3 >> >> If you want the function itself you use: >> >> f > > How do you call a function of no arguments? There's no such thing. All functions take one argument and return a value. As functions don't have side-effects, there is seldom much point in having a function with no arguments or which doesn't return a value. In cases where it is useful (i.e. a value must have function type), you can use the unit type "()" (essentially a zero-element tuple), e.g.: f () = 1 or: f x = () |