From: Jonathan Gardner on
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
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
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
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
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 = ()