Symbols as parameters?

M

Martin Drautzburg

Hello all,

When passing parameters to a function, you sometimes need a paramter
which can only assume certain values, e.g.

def move (direction):
...
If direction can only be "up", "down", "left" or "right", you can solve
this by passing strings, but this is not quite to the point:

- you could pass invalid strings easily
- you need to quote thigs, which is a nuisance
- the parameter IS REALLY NOT A STRING, but a direction

Alternatively you could export such symbols, so when you "import *" you
have them available in the caller's namespace. But that forces you
to "import *" which pollutes your namespace.

What I am really looking for is a way

- to be able to call move(up)
- having the "up" symbol only in the context of the function call

So it should look something like this

.... magic, magic ...
move(up)
.... unmagic, unmagic ...
print up

This should complain that "up" is not defined during the "print" call,
but not when move() is called. And of course there should be as little
magic as possible.

Any way to achieve this?
 
A

Andre Engels

Hello all,

When passing parameters to a function, you sometimes need a paramter
which can only assume certain values, e.g.

       def move (direction):
               ...
If direction can only be "up", "down", "left" or "right", you can solve
this by passing strings, but this is not quite to the point:

       - you could pass invalid strings easily
       - you need to quote thigs, which is a nuisance
       - the parameter IS REALLY NOT A STRING, but a direction

Alternatively you could export such symbols, so when you "import *" you
have them available in the caller's namespace. But that forces you
to "import *" which pollutes your namespace.

What I am really looking for is a way

       - to be able to call move(up)
       - having the "up" symbol only in the context of the function call

So it should look something like this

... magic, magic ...
move(up)
... unmagic, unmagic ...
print up

This should complain that "up" is not defined during the "print" call,
but not when move() is called. And of course there should be as little
magic as possible.

Any way to achieve this?

It probably can be done, but in my opinion even it can, it would be
ugly. I would just define "up" as some global constant - I don't see
why it would be a problem that it's defined when you don't need it. In
fact, I think it would be beneficial - you can then have
direction-valued variables, so that you can (for example) implement
"go the same direction I went last time". If that kind of thing
happens more often, it might be useful to have a Direction class, to
be able to easily program in things like "the opposite of up is down"
and "right from right is back".
 
A

Alf P. Steinbach

* Martin Drautzburg:
Hello all,

When passing parameters to a function, you sometimes need a paramter
which can only assume certain values, e.g.

def move (direction):
...
If direction can only be "up", "down", "left" or "right", you can solve
this by passing strings, but this is not quite to the point:

- you could pass invalid strings easily
- you need to quote thigs, which is a nuisance
- the parameter IS REALLY NOT A STRING, but a direction

Alternatively you could export such symbols, so when you "import *" you
have them available in the caller's namespace. But that forces you
to "import *" which pollutes your namespace.

What I am really looking for is a way

- to be able to call move(up)
- having the "up" symbol only in the context of the function call

So it should look something like this

... magic, magic ...
move(up)
... unmagic, unmagic ...
print up

This should complain that "up" is not defined during the "print" call,
but not when move() is called. And of course there should be as little
magic as possible.

Any way to achieve this?
.... print( "move " + str( direction ) )
........ up = 42
.... move( up )
....
move 42Traceback (most recent call last):


Of course it's an abuse of the language. :)

So I wouldn't recommend it, but it's perhaps worth having seen it.


Cheers & hth.,

- Alf

PS: I hope this was not a homework question.
 
J

Javier Collado

Hello,

I'd say that isn't totally incorrect to use strings instead of
symbols. Please note that in other programming languages symbols,
atoms and the like are in fact immutable strings, which is what python
provides by default.

Best regards,
Javier
 
B

Bearophile

Martin Drautzburg, having symbols spread in the namespace is bad. And
too much magic is even worse. You seem to need something like an enum
that must be used with its qualified name, as:
move(direction.up)
That works well unless the symbols name are keywords.

Creating a small class like this (that warns if you give it a string
that contains a keyword) looks not too much hard:
direction = Enum("up", "down", "left", "right")
Or:
direction = Enum("up, down, left, right")
Or:
direction = Enum("up down left right")

Bye,
bearophile
 
I

Iain King

Hello all,

When passing parameters to a function, you sometimes need a paramter
which can only assume certain values, e.g.

        def move (direction):
                ...
If direction can only be "up", "down", "left" or "right", you can solve
this by passing strings, but this is not quite to the point:

        - you could pass invalid strings easily
        - you need to quote thigs, which is a nuisance
        - the parameter IS REALLY NOT A STRING, but a direction

Alternatively you could export such symbols, so when you "import *" you
have them available in the caller's namespace. But that forces you
to "import *" which pollutes your namespace.

What I am really looking for is a way

        - to be able to call move(up)
        - having the "up" symbol only in the context of the function call

So it should look something like this

... magic, magic ...
move(up)
... unmagic, unmagic ...
print up

This should complain that "up" is not defined during the "print" call,
but not when move() is called. And of course there should be as little
magic as possible.

Any way to achieve this?

class Direction(object):
pass

def is_direction(d):
return type(d)==Direction

up = Direction()
down = Direction()
left = Direction()
right = Direction()

Now you can do your move(up), print up, etc. You can also check a
valid direction was passed in by calling is_direction. 'Course, you
can extend this so it does something a little more useful:

class Direction(object):
def __init__(self, vx=0, vy=0):
self.vx = vx
self.vy = vy

up = Direction(0, -1)
down = Direction(0, 1)
left = Direction(-1, 0)
right = Direction(1, 0)

def move(direction):
spaceship.x += direction.vx
spaceship.y += direction.vy

Iain
 
A

Alf P. Steinbach

Huh? I guess you meant to reply to the OP, not me.

Cheers,

- Alf

* Javier Collado:
 
C

Carl Banks

Hello all,

When passing parameters to a function, you sometimes need a paramter
which can only assume certain values, e.g.

        def move (direction):
                ...
If direction can only be "up", "down", "left" or "right", you can solve
this by passing strings, but this is not quite to the point:

        - you could pass invalid strings easily
        - you need to quote thigs, which is a nuisance
        - the parameter IS REALLY NOT A STRING, but a direction

Nothing you can pass to the function is really a direction. A symbol
is no more a direction than a string is.

Alternatively you could export such symbols, so when you "import *" you
have them available in the caller's namespace. But that forces you
to "import *" which pollutes your namespace.

No it doesn't. You can still write module.UP in the function call, or
you can write from module import UP.

What I am really looking for is a way

        - to be able to call move(up)
        - having the "up" symbol only in the context of the function call

Short answer is, you can't do it.

Long answer is, you don't really want to have a symbol that's only in
context during the function call, because you might just want to write
some code that operates on directions (e.g., return random.choice
([UP,DOWN]), but it's a moot point since you can't do it.
So it should look something like this

... magic, magic ...
move(up)
... unmagic, unmagic ...
print up

This should complain that "up" is not defined during the "print" call,
but not when move() is called. And of course there should be as little
magic as possible.

Any way to achieve this?

Apart from writing a custom DSL (domain specific language), no.

It is not, in case your were wondering, a feature that would be easily
added to Python (the moratorium on new syntax notwithstanding).
Python wouldn't be able to do this at compile time (since Python
doesn't know what symbols refer to till run time). I convinced myself
that it would be techincally possible to do it at run time, but at a
penalty of higher function call overhead (which is already high enough
as it is). And with the performance hit, extra scoping complexity,
the inability to be used outside the function context, and no real
benefit except to save typing, I don't see it ever being approved.


Carl Banks
 
A

Alf P. Steinbach

* Carl Banks:
On Jan 20, 11:43 pm, Martin Drautzburg <[email protected]> [snip]
What I am really looking for is a way

- to be able to call move(up)
- having the "up" symbol only in the context of the function call

Short answer is, you can't do it.

On the contrary, it's not difficult to do.

I provided an example in my answer to the OP (first reply in the thread).

However, it's IMHO an abuse of the language, not something that one should do.


Cheers & hth.,

- Alf
 
J

Jean-Michel Pichavant

Martin said:
Hello all,

When passing parameters to a function, you sometimes need a paramter
which can only assume certain values, e.g.

def move (direction):
...
If direction can only be "up", "down", "left" or "right", you can solve
this by passing strings, but this is not quite to the point:

- you could pass invalid strings easily
- you need to quote thigs, which is a nuisance
- the parameter IS REALLY NOT A STRING, but a direction

Alternatively you could export such symbols, so when you "import *" you
have them available in the caller's namespace. But that forces you
to "import *" which pollutes your namespace.

What I am really looking for is a way

- to be able to call move(up)
- having the "up" symbol only in the context of the function call

So it should look something like this

... magic, magic ...
move(up)
... unmagic, unmagic ...
print up

This should complain that "up" is not defined during the "print" call,
but not when move() is called. And of course there should be as little
magic as possible.

Any way to achieve this?
in move.py

def move(direction):
print "moving %s" % direction

move.UP = 'up'
move.DOWN = 'down'

Then
moving up


JM
 
S

Stefan Behnel

Alf P. Steinbach, 21.01.2010 09:30:
* Martin Drautzburg:

Looks like a terribly bad design to me.

... print( "move " + str( direction ) )
...
... up = 42
... move( up )
...
move 42
Traceback (most recent call last):


Of course it's an abuse of the language. :)

And, of course, it's totally useless as the move() function doesn't know
about the 'up' thing in the first place.

Stefan
 
S

Stefan Behnel

Alf P. Steinbach, 21.01.2010 11:38:
* Carl Banks:
On Jan 20, 11:43 pm, Martin Drautzburg <[email protected]> [snip]
What I am really looking for is a way

- to be able to call move(up)
- having the "up" symbol only in the context of the function
call

Short answer is, you can't do it.

On the contrary, it's not difficult to do.

I provided an example in my answer to the OP (first reply in the thread).

Erm, no, you didn't. You showed a) how to pass a string constant into a
function and b) how to pass a value from a bound variable. None of that is
helpful to the OP's problem.

Stefan
 
A

Alf P. Steinbach

* Stefan Behnel:
Alf P. Steinbach, 21.01.2010 09:30:

Looks like a terribly bad design to me.

That it is, in Python.

And, of course, it's totally useless as the move() function doesn't know
about the 'up' thing in the first place.

Hm, it seems as if you thought that the example was *literally* what the OP
should do.

It was not: it just demonstrated the possibility.

Consider replacing the assignment with whatever, or alternatively, consider that
perhaps 42 is indeed the value of "up" that the move() function knows about.


Cheers & hth.,

- Alf
 
A

Alf P. Steinbach

* Stefan Behnel:
Alf P. Steinbach, 21.01.2010 11:38:
* Carl Banks:
On Jan 20, 11:43 pm, Martin Drautzburg <[email protected]> [snip]
What I am really looking for is a way

- to be able to call move(up)
- having the "up" symbol only in the context of the function
call
Short answer is, you can't do it.
On the contrary, it's not difficult to do.

I provided an example in my answer to the OP (first reply in the thread).

Erm, no, you didn't. You showed a) how to pass a string constant into a
function and b) how to pass a value from a bound variable. None of that is
helpful to the OP's problem.

Perhaps look again at that example. It demonstrates exactly what the OP asks for.


Cheers & hth.,

- Alf
 
D

Dave Angel

Martin said:
Hello all,

When passing parameters to a function, you sometimes need a paramter
which can only assume certain values, e.g.

def move (direction):
...
If direction can only be "up", "down", "left" or "right", you can solve
this by passing strings, but this is not quite to the point:

- you could pass invalid strings easily
- you need to quote thigs, which is a nuisance
- the parameter IS REALLY NOT A STRING, but a direction

Alternatively you could export such symbols, so when you "import *" you
have them available in the caller's namespace. But that forces you
to "import *" which pollutes your namespace.

What I am really looking for is a way

- to be able to call move(up)
- having the "up" symbol only in the context of the function call

So it should look something like this

... magic, magic ...
move(up)
... unmagic, unmagic ...
print up

This should complain that "up" is not defined during the "print" call,
but not when move() is called. And of course there should be as little
magic as possible.

Any way to achieve this?
My favorite answer provided by others was adding the attributes to the
function right after the function definition, then using
move(move.up)

But another approach is to define the function as:

def move(up=False, down=False, right=False, left=False):
if up:
...
if down:
....

and call it as:

move(up=True)

DaveA
 
C

Carl Banks

* Carl Banks:
On Jan 20, 11:43 pm, Martin Drautzburg <[email protected]> [snip]
What I am really looking for is a way
        - to be able to call move(up)
        - having the "up" symbol only in the context of the function call
Short answer is, you can't do it.

On the contrary, it's not difficult to do.

I provided an example in my answer to the OP (first reply in the thread).

Your example doesn't remotely do what the OP was asking for. In fact
your example is so preposterous I question your sanity.

However, it's IMHO an abuse of the language, not something that one should do.

Usually people abuse the language to achieve something (ostensibly)
useful. Your example is so useless I don't think I would even call it
abuse.

As best as I can tell, what it is is you attempting to make yourself
look like some kind of badass by answering some absurdly literal
interpretation of the OP's question.

Except you haven't even done that:

class using_directions:
up = 42
move( up )
print up # <- clearly not confined to context of function call



Carl Banks
 
D

Diez B. Roggisch

Am 21.01.10 12:58, schrieb Alf P. Steinbach:
* Stefan Behnel:
Alf P. Steinbach, 21.01.2010 11:38:
* Carl Banks:
On Jan 20, 11:43 pm, Martin Drautzburg <[email protected]>
[snip]
What I am really looking for is a way

- to be able to call move(up)
- having the "up" symbol only in the context of the function
call
Short answer is, you can't do it.

On the contrary, it's not difficult to do.

I provided an example in my answer to the OP (first reply in the
thread).

Erm, no, you didn't. You showed a) how to pass a string constant into a
function and b) how to pass a value from a bound variable. None of
that is
helpful to the OP's problem.

Perhaps look again at that example. It demonstrates exactly what the OP
asks for.

Perhaps look again at the requirements:

"""
- the parameter IS REALLY NOT A STRING, but a direction
"""

Diez
 
A

Alf P. Steinbach

* Carl Banks:
* Carl Banks:
On Jan 20, 11:43 pm, Martin Drautzburg <[email protected]> [snip]

What I am really looking for is a way
- to be able to call move(up)
- having the "up" symbol only in the context of the function call
Short answer is, you can't do it.
On the contrary, it's not difficult to do.

I provided an example in my answer to the OP (first reply in the thread).

Your example doesn't remotely do what the OP was asking for. In fact
your example is so preposterous I question your sanity.

Your first sentence is incorrect, your second sentence is a silly attempt at
getting personal.

Usually people abuse the language to achieve something (ostensibly)
useful. Your example is so useless I don't think I would even call it
abuse.

You are correct that it's useless. The OP asked for a construct to do a useless
thing. The presented construct does exactly what the OP asked for: useless.

As best as I can tell, what it is is you attempting to make yourself
look like some kind of badass by answering some absurdly literal
interpretation of the OP's question.

Hm, there are ways to do things, even the ad hominem thing. You just present
yourself as one using strong words when you're proven wrong. Myself I'm not
foreign to strong words :), but I wouldn't dream of applying them to a person.

The above is very, uh, primitive.

Besides, it's quite silly to get angry when you're proved to be wrong. :)

Except you haven't even done that:

class using_directions:
up = 42
move( up )
print up # <- clearly not confined to context of function call

You know, I didn't think of that ingenious thing, that it would be possible to
*modify* the example so that it no longer fit the OP's literal description. Thx!


Cheers & hth.,

- Alf
 
A

Alf P. Steinbach

* Diez B. Roggisch:
Am 21.01.10 12:58, schrieb Alf P. Steinbach:
* Stefan Behnel:
Alf P. Steinbach, 21.01.2010 11:38:
* Carl Banks:
On Jan 20, 11:43 pm, Martin Drautzburg <[email protected]>
[snip]
What I am really looking for is a way

- to be able to call move(up)
- having the "up" symbol only in the context of the function
call
Short answer is, you can't do it.

On the contrary, it's not difficult to do.

I provided an example in my answer to the OP (first reply in the
thread).

Erm, no, you didn't. You showed a) how to pass a string constant into a
function and b) how to pass a value from a bound variable. None of
that is
helpful to the OP's problem.

Perhaps look again at that example. It demonstrates exactly what the OP
asks for.

Perhaps look again at the requirements:

"""
- the parameter IS REALLY NOT A STRING, but a direction
"""

So?


Cheers & hth.,

- Alf
 
D

Diez B. Roggisch

Am 21.01.10 19:48, schrieb Alf P. Steinbach:
* Diez B. Roggisch:
Am 21.01.10 12:58, schrieb Alf P. Steinbach:
* Stefan Behnel:
Alf P. Steinbach, 21.01.2010 11:38:
* Carl Banks:
On Jan 20, 11:43 pm, Martin Drautzburg <[email protected]>
[snip]
What I am really looking for is a way

- to be able to call move(up)
- having the "up" symbol only in the context of the function
call
Short answer is, you can't do it.

On the contrary, it's not difficult to do.

I provided an example in my answer to the OP (first reply in the
thread).

Erm, no, you didn't. You showed a) how to pass a string constant into a
function and b) how to pass a value from a bound variable. None of
that is
helpful to the OP's problem.

Perhaps look again at that example. It demonstrates exactly what the OP
asks for.

Perhaps look again at the requirements:

"""
- the parameter IS REALLY NOT A STRING, but a direction
"""

So?

Oh please. You claim you provided exactly what the OP asked for. But in
the body of move, all you can do is to compare the direction parameter
tco "up", not to UP. So no, you provided *something*, but not what the
OP asked for.

Diez
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top