# How to break up function definitions across several lines?

if i write a function definition and i break it up across several lines, the sage prepocessor complains:

phi(epsilon, Q, r) = 1/(4*pi*
epsilon
)*Q/r

show(phi(1,2,3))


the sage prepocessor complains:

sage demo.sage
File "demo.sage.py", line 6
__tmp__=var("epsilon,Q,r"); phi = symbolic_expression(_sage_const_1 /(_sage_const_4 *pi*).function(epsilon,Q,r)
^
SyntaxError: invalid syntax


While this is a very short function that is easily kept on one line, I do have rather long and intricate ones which I would like to break up (and potentially comment) over several lines.

Linebreaks with backslash as the last char of the line don't work:

cat demo.sage
phi(epsilon, Q, r) = 1/(4*pi*\
epsilon\
)*Q/r

show(phi(1,2,3))

% sage demo.sage
File "demo.sage.py", line 6
__tmp__=var("epsilon,Q,r"); phi = symbolic_expression(_sage_const_1 /(_sage_const_4 *pi* * BackslashOperator() * ).function(epsilon,Q,r)
^
SyntaxError: invalid syntax


How do I do that?

edit retag close merge delete

Sort by » oldest newest most voted

Hello, @stockh0lm. This seems to be a problem with the preprocessor, since it is assuming all \ to be a matrix operation (i.e., the Matlab-style operator for solving systems of linear equations).

As a workaround you could use consistent indentation and wrap the code with parenthesis, so that Sage's preparser understands the complete extension of your code. The following worked for me:

phi(epsilon, Q, r) = (1 / (4 * pi
* epsilon)
* Q / r)

show(phi(1,2,3))


Notice all lines defining phi are equally indented, and I started and finished its definition with parenthesis. The preparser seems to assume the code defining the function ends on the line with the last parenthesis, so we are forcing it to consider our complete definition.

Also, I am using the PEP 8 convention of breaking a line BEFORE an operator, i.e., the asterisk doesn't end a line, but it starts one. (This last convention has nothing to do with the working of the code; it's just a convention.)

more

how weird, this does not work for me, either:

% sage demo.sage
File "demo.sage.py", line 8
* Q/r
^
IndentationError: unexpected indent

% cat demo.sage
phi(epsilon, Q, r) = 1/(4*pi
* epsilon)
* Q/r

show(phi(1,2,3))

( 2019-04-27 00:45:42 +0200 )edit

Yes, sorry. You're right! This is weird, but Sage's preparser thinks the expression extends until the line that closes the last parenthesis (in your code until the end of the second line). Thus, the third line is not considered to be part of the definition, and Sage doesn't know why you indented.

I was lucky! Notice I closed the parenthesis on the last line (I think this is not good style), so in my case, it worked. Funny result!

Try wrapping all the expression in parenthesis, like:

phi(epsilon, Q, r) = (1/(4*pi
* epsilon)
* Q/r)

show(phi(1,2,3))

( 2019-04-27 01:42:10 +0200 )edit

this works! Thank you! - can you please put it in a proper answer, instead of a comment, so i can upvote and accept it?

( 2019-04-27 16:40:29 +0200 )edit

Hello, @stockh0lm. I think this webpage doesn't allow multiple answers from the same user, so I have edited my original answer to include my comment that gave you the correct answer. Therefore, you can mark that as an answer. Thank you!

( 2019-04-27 20:39:39 +0200 )edit

This does also work without indentation

phi(epsilon, Q, r) = (1 / (4 * pi
* epsilon)
* Q / r)

( 2019-04-27 22:02:52 +0200 )edit

This is indeed a bug of the preparse function. Your syntax is perfectly valid in Python

>>> A = 1 + (3*
... 4
... ) * 2
25


However Sage preparser function is not smart in matching the start and end of an instruction.

sage: s = """phi(epsilon, Q, r) = 1/(4*pi*
....:                         epsilon
....: )*Q/r"""
sage: print(s)
phi(epsilon, Q, r) = 1/(4*pi*
epsilon
)*Q/r
sage: print(preparse(s))
__tmp__=var("epsilon,Q,r"); phi = symbolic_expression(Integer(1)/(Integer(4)*pi*).function(epsilon,Q,r)
epsilon
)*Q/r


Somehow, only the first line went transformed into a function. If you call directly preparse_calculus (which is the part that perform the preparsing of the instruction defining the function) it works

sage: from sage.repl.preparse import preparse_calculus
sage: print(preparse_calculus(";" + s + ";"))
;__tmp__=var("epsilon,Q,r"); phi = symbolic_expression(1/(4*pi*
epsilon
)*Q/r).function(epsilon,Q,r);


(Don't ask me why, but the function preparse_calculus needs a ";" at the begining and the end of the instruction). This can then be executed manually

sage: exec(preparse_calculus(";" + s + ";")[1:-1])
sage: phi
(epsilon, Q, r) |--> 1/4*Q/(pi*epsilon*r)


Note that this problem has been reported 8 years ago in trac ticket #11621.

more

Hi,

you can use line breaks line breaks

phi(epsilon, Q, r) = 1/(4*pi* \
epsilon \
)*Q/r

show(phi(1,2,3))


Worked for me in the sage command line v8.2

more

No.

File "demo.sage.py", line 6
__tmp__=var("epsilon,Q,r"); phi = symbolic_expression(_sage_const_1 /(_sage_const_4 *pi* * BackslashOperator() * ).function(epsilon,Q,r)
^
SyntaxError: invalid syntax


actually i had tried that, and i cant. see error above.

( 2019-04-26 17:06:58 +0200 )edit