Free variables?

Is there a way I can use variables in algorithms without defining them directly? I need a sort of “everything that x” for a project I’m working on.
Sorry I don’t have code for this one but I don’t think it would help!

Can you provide example code of how it would be used? Write code looking
like what you’d like to be able to say, and we may be able to tell you
how to say that in Python.

There’s a filter() builtin function for taking only part of some
iterable, and there are list comprehensions which have an if clause:

[ x for x in list_of_xs if x > 0 ]

Cheers,
Cameron Simpson cs@cskk.id.au

Let’s see if I can come up with something simple…

from typing import Union, Callable, Optional


def add(a: int, b: Optional[int] = None) -> Union[int, Callable[[int], int]]:
    def _add(a, b):
        return a + b

    if b is None:
        return lambda b: _add(a, b)
    return _add(a.b)

Thanks for the example, but I don’t understand: how do you intend to use the “for everything that x” in this example? In general, you rather want to gather objects explicitly in lists. Can you provide a mock example with invalid code showing what you would like to be able to write?

Also note that your _add function is available as operator.add.

Hi Tom,

Strictly speaking, there are no “variables” in Python. There just are names pointing to objects. Two “names” can e.g. point to the very same object - example:

a = [1,2,3]
b = a
b[1] = 5
a

leads to [1, 5, 3].

So, if you ask me, the answer is: “no”.

Cheers, Dominik

Ah. So this is a function which adds a and b if they’re both provided,
but returns a callable to add just b if you have a but not yet b?

What you wrote is pretty good. Without the type annotations (which bury
the “=None” below:

def add(a, b=None):
    if b is None:
        return lambda b: a + b
    return a + b

That should support:

x = add(1, 3)
y = add(1)(3)

Actually, that’s just what you wrote now that I compare them.

So… in what way was what you wrote not what you wanted to be able to
write?

Cheers,
Cameron Simpson cs@cskk.id.au

I think you are after currying and partial function application.

>>> from functools import partial

>>> import operator

>>> 

>>> def add(a, b=None):

...     if b is None:

...             return partial(operator.add, a)

...     else:

...             return a+b

... 

>>> add(5, 6)

11

>>> add(5)(6)

11

Here’s a good example as to what I’m talking about:

found = False
if x < 0:
print( “x is negative” )
found = True
else:
for i in range( 100 ):
if i > x:
print( “x is between %d and %d” % ( i, i - 1 ) )
found = True
break

if not found:
print( “x is > 99” )

How does this work?

Something manked your indenting. I’ve made a guess.

Well it sets found to False. Then it elimiates x < 0, then it examines
all the values from 0 through 99 and compares them with x, and sets
found to True is that’s so and exits the loop (entirely for efficiency).

Obviously for an integer range this is laborious overkill, but if you
replace range(100) with some arbitrary set of values it may fall into
the approach above: you need to test x against every value.

The idea here is that you’re trying to find out if x in in a set of
values (or perhaps some continuous domain or something).

I don’t see what that has to do with “Free variables”. I’m thinking I
have no idea what you mean by that term.

Cheers,
Cameron Simpson cs@cskk.id.au

What I meant to ask was how a variable can have nothing but it’s own context

“true” works fine

Thanks to everyone for pointing me in the right direction!

1 Like

[heat jack wrote]

"What I meant to ask was how a variable can have nothing but it’s own

context"

What does that mean?

Free variable has a specific meaning in programming, but you don’t

seem to be using that. In this function:

def func():

    x = 1

    print(x + y)

x is a bound variable (it has the value 1) while y is a

free variable.

If you call that function, one of two things can happen:

  • the interpreter finds a value for y in a surrounding scope, say a

    global variable;

  • or there is no global variable y (or any other surrounding scope),

    so y remains a free variable, and the interpreter is forced to

    raise an exception.

Is that what you mean when you talk about free variables?

By the way, “true” (in quotes) would be a string, not a variable.

Although you could call a variable “true”, although that would be

confusing since there is a built-in True constant.

There is in beginning term “union” ? resp. import union ?
Is “union” not Java ?

Ruby… most would use java so I understand why you got confused