Function declarations ?

A

Andre Majorel

Is there a way to keep the definitions of the high-level
functions at the top of the source ? I don't see a way to
declare a function in Python.

Thanks in advance.
 
D

D'Arcy J.M. Cain

Is there a way to keep the definitions of the high-level
functions at the top of the source ? I don't see a way to
declare a function in Python.

You don't declare functions in Python. You simply define them. You
could define all your functions first and then call them. This is
probably not a bad idea anyway. However, I suspect it doesn't solve
your problem but since you haven't articulated it I can't tell.

Don't present a solution and ask how it could work. Tell us what
problem you are trying to solve and maybe we can suggest a solution.
 
A

Asen Bozhilov

Andre said:
Is there a way to keep the definitions of the high-level
functions at the top of the source ? I don't see a way to
declare a function in Python.

I am not a Python developer, but Pythonic way of definition not
declaration is definitely interesting. Languages with variable and
function declarations usually use hoisted environment. JavaScript is
the perfect example. Hoisted environment allows you to use call
expression before the physical declaration of the function in the
source text.

e.g.

foo();

function foo() {}

This code does not throw ReferenceError or TypeError in JavaScript. It
calls `foo' exactly because it is used a hoisted environment. More
precisely on entering in some context global or function JS engine
define all function declarations as local scoped variables. While this
has its advantages, it has a really big drawback. It cannot support
default arguments which are bound to local variables.

x = 10
def f(y = x):
print y

f() #10

This in hoisted environment cannot be implemented, because assignment
is evaluating during the execution of the code, not on entering in
specific context. So the interpreter is not able to predict the value
for y here.

Hope this helps, why Python use definitions instead of declarations.
 
A

Andre Majorel

Languages with variable and function declarations usually use
hoisted environment.

Hoisted ? With a pulley and a cable ?
JavaScript is the perfect example. Hoisted environment allows
you to use call expression before the physical declaration of
the function in the source text.

The issue here is not the ability to call a function before its
declaration. It's being able to do so before its definition.
Hope this helps, why Python use definitions instead of
declarations.

It's not either/or. Any language has to provide a way to define
functions whether or not it provides a way to declare them.

Anyway, it seems the Python way to declare a function is

def f ():
pass

Thanks everyone.
 
S

Steven D'Aprano

Hoisted ? With a pulley and a cable ?

No, with a compiler.

"Hoisting" in computing refers to the idea of "lifting" variables or code
outside of one block into another. For example, an optimization technique
is to hoist repeated if statements outside the loop. E.g. instead of:

for i in range(1000000):
if condition:
spam(i)
else:
ham(i)

Assuming that condition doesn't change as the loop runs (spam and ham
have no side-effects), this can be optimized to:

if condition:
for i in range(1000000):
spam(i)
else:
for i in range(1000000):
ham(i)

That's called hoisting.

In Python, which has first-class functions, we can do better by avoiding
code duplication:

if condition:
func = spam
else:
func = ham
for i in range(1000000):
func(i)


But either way, the decision is lifted (hoisted) out of the loop.


The issue here is not the ability to call a function before its
declaration. It's being able to do so before its definition.

Obviously you can't call a function before it is defined.

As a language without type declarations, Python doesn't need functions to
be declared ahead of time. I can define a function that calls another:
.... return 2*spam(x)
....
and so long as I eventually define spam() before calling ham(), all is
good:
.... def spam(x):
.... return x-1
....4


I can even re-define spam at runtime, and ham will see the difference:
.... return "spam "*x
....'spam spam spam spam spam spam '


But what I can't do in Python is execute ham() BEFORE spam() is defined.
(Well, I can, but I get an error.) Even if spam() is defined lower down
in the source code, Python won't see it.

As I understand it, that's not how Javascript works. The parser does two
passes over the source file, instead of one like Python. If it sees a
function definition, it hoists it out into the global environment, and
then on the second pass executes the code as needed. Using Python syntax,
this is an error:

def ham(x):
return 2*spam(x)

print(ham(3))

def spam(x):
return x-1

but Javascript will accept it perfectly fine, and output 4.


Here's another model: Pascal. Because Pascal does type checking at
compile time, it will reject the function ham() and raise a compiler
error, because it can't test the argument and output type of spam(). So
you would need a *forward declaration*. Using a mix of Python and Pascal
syntax:


# declare spam without a definition
forward spam(x: integer): integer

# declare and define ham
def ham(x: integer): integer
return 2*spam(x)

print(ham(2))

# define spam (declaration must match the earlier one!)
def spam(x: integer): integer
return x-1


It's not either/or. Any language has to provide a way to define
functions whether or not it provides a way to declare them.

Exactly. Pascal has both; Python only has definitions.

Anyway, it seems the Python way to declare a function is

def f ():
pass

That doesn't declare a function. It defines a do-nothing function. `def`
is an executable statement which happens at runtime, not a compile-time
declaration.
 
J

John Nagle

Hoisted ? With a pulley and a cable ?

There are languages with definitions and in which
the compiler looks ahead. FORTRAN, for example.
Python doesn't work that way. Nor do C and the
languages derived from it, because the syntax
is context-dependent. (In C++, "A b;" is ambiguous
until after the declaration of A. In
Pascal-derived languages, you write "var b: A;",
which is parseable before you know what A is.
So declarations don't have to be in dependency order.)

None of this is relevant to Python, but that's
what "hoisted" means in this context..

John Nagle
 
G

Gregory Ewing

Steven said:
"Hoisting" in computing refers to the idea of "lifting" variables or code
outside of one block into another.

I'm not sure it's the right term for what's happening here,
though. Nothing is being lifted to a higher level -- the
functions remain at the same level they were written at.
Here's another model: Pascal. Because Pascal does type checking at
compile time, it will reject the function ham() and raise a compiler
error,

It's more that Pascal is designed to make single-pass
compilation easy. It's possible to support out-of-order
declarations with compile-time type checking using two
passes; Pyrex does this, for example.
 
G

Gregory Ewing

Tim said:
No, that DEFINES a function.

Actually, it's more illuminating to say that it *creates* a function.

The 'def' statement in Python is an executable statement. Executing
it has the effect of creating a function object and binding it to
the indicated name. Before that has happened, attempting to execute
any code referring to that name will fail.

Conversely, the function name doesn't need to be bound until the
code referring to it is actually executed. So...
def g():
return f()
def f():
return 3
print g()

works because by the time g is *called*, both def statements
have been executed, and both function names have therefore been
bound.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,783
Latest member
RickeyDort

Latest Threads

Top