Currently, anytime there is a command that contains a noun and an
adjective, there seems to be debate about what order they should be
listed. For example, there have been debates over whether to name a
function right_eigenvectors and eigenvectors_right. It seems the big
argument for eigenvectors_right is that it is easy to find with tab
completion (i.e., if you want to do a eigenvectors, you type
eigenvectors<tab> and pick the right function). The big argument for
right_eigenvectors is that is how things are normally said in English
(the adjective precedes the noun). So to satisfy both, we use both
names, which leads to cluttered namespace in which lots of function
names are actually the same function.
The other day, someone suggested finding a function using syntax similar to:
*eigenvectors*?
This finds all functions that contain the word "eigenvectors". For a
matrix, for example, we get:
sage: m=random_matrix(ZZ,5)
sage: m.*eigenvectors*?
m.eigenvectors_left
m.eigenvectors_right
m.left_eigenvectors
m.right_eigenvectors
If tab completion returned the above choices instead of just the
functions that started with "eigenvectors", I believe that would satisfy
the crowd that wants function names to be easy to complete and guess
using tab completion.
What if, at least for the notebook, and maybe for the command line too,
we listed two sets of completions: the first would be the list given
now, and the second would be the list given above? In other words, if
in the notebook, you typed m.eigenvectors<tab>, you would get a box
containing two lists:
_______________________________________
| |
| list of current completions |
| |
|--------------------------------------
| list of extended completions |
| given by the *word*? trick |
|_____________________________________|
What do people think? I think this would finally answer the tension
between the people that want useful tab completion and the people who
want the function names to look "right".
Too bad English doesn't put the adjectives after the noun :).
Jason
In the notebook? +1. This is such a good idea I might incorporate it
into sage-mode.
Nick
+1 for extending tab-completion to mention these extra completions
(both for notebook and command-line).
The way you wrote it, the second list would always be a superset of
the first; I think the first list should be removed from the second.
And maybe the second list should be omitted altogether if it's too
big? For instance, if I type foo.e<TAB>, I'm probably not interested
in the list of all method names that include an 'e' somewhere.
BTW, when I saw the topic, I was expecting to read something like
"Let's use fewer aliases to reduce the length of tab-completion
lists." The message "Let's increase the length of tab-completion
lists to use fewer aliases" was quite a surprise :)
Carl
Good point. I agree.
> And maybe the second list should be omitted altogether if it's too
> big? For instance, if I type foo.e<TAB>, I'm probably not interested
> in the list of all method names that include an 'e' somewhere.
Yes, but I'm not sure how to tell if the list is too big. I certainly
have instances when I want to type the name of a command that starts
with e, but I wasn't sure exactly how the command was spelled, so I did
something like foo.e<TAB>.
Can you think of a good criteria for telling if the extended completion
list is not what the user wanted?
Jason
This is a bit arbitrary for my tastes, but I think it (or somthing
similar) could work:
If you type foo.X<TAB>, where X is only one or two characters, then
the extended completion list checks for *_X*. Otherwise (if X is
three or more characters) then the extended completion list is *X*.
Carl
I like this idea much better. I often use tab completion not just to
find methods, but because it's faster than typing them out
completely. Cluttering foo.ei<tab> with everything that contains ei
would be a step backwards.
- Robert
+1! For exactly the reasons Robert Bradshaw gave:
> I like this idea much better. I often use tab completion not just to
> find methods, but because it's faster than typing them out
> completely. Cluttering foo.ei<tab> with everything that contains ei
> would be a step backwards.
Franco
--
I disagree, we should break whatever we dislike for a *X.0* release (+
DeprecationWarning for some months) Sage is a young agile fast moving project
and shouldn't be burdened with all kinds of old stuff just lying around. I
really liked Roman's comment on this matter, i.e. that we should change stuff
around while we can.
It seems to me: Sage isn't done yet and pretending it was does more harm than
good by making it more difficult to contribute.
Also, this whole 'don't break people's code' thing is a sham to some extend
anyway since the behavior of functions changes so much even in minor releases
anyway. Also it is those kind of changes that lead to subtle bugs that are
hard to notice in contrast to someting like an AttributeError.
Cheers,
Martin
--
name: Martin Albrecht
_pgp: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x8EF0DC99
_otr: 47F43D1A 5D68C36F 468BAEBA 640E8856 D7951CCF
_www: http://www.informatik.uni-bremen.de/~malb
_jab: martinr...@jabber.ccc.de
I have to admit that I don't have any concrete example, so I take your point.
It is a somewhat fuzzy even psychological issue I think. But since I have to
admit it is fuzzy, I take it back until further notice.
I can think of hypothetical examples but nothing concrete right now from the
top of my head.
> > Also, this whole 'don't break people's code' thing is a sham to some
> > extend anyway since the behavior of functions changes so much even in
> > minor releases anyway. Also it is those kind of changes that lead to
> > subtle bugs that are hard to notice in contrast to someting like an
> > AttributeError.
>
> Again: Please give an example. Behavioral are either unintentional or
> bugfixes AFAIK.
Sure thing:
http://www.sagemath.org/hg/sage-main/annotate/b3006824b208/sage/rings/integer.pyx
broke my code in a subtle way, i.e. it didn't crash but gave wrong answers. Of
course, I could easily track it down and fix my code. Sure thing it wasn't
intended to break my code but it did. Maintaining backward compatibility for
this function however would have meant to stick with my ad hoc decision that
digits() should have base two.
At least some code in Sage is not based on a lengthly well thought through
design process but on a developer's 'taste'. The backward compatibility rule
would mean to stick to this decision until the end of time.
> I think you really overestimate the pain deprecations and removal of
> functionality does cause to the casual user.
Do you mean to say 'underestimate'?
> The GAP 3 -> GAP 4
> transition with ample breakage was quite painful to a lot of people
> and there are even some examples of very nice code that never moved
> from GAP 3 to GAP 4 to this day, either because the author didn't care
> because he kept using GAP 3 or alternatively because the author had
> left academia and was no longer interested in porting the code.
> Another example of when a user community to a large extend did not
> move from one version to the incompatible followup release is Macaulay
> 2.
Sure, stuff like this happens (a lot), but I really like Roman's answer to
this: Make sure your new version is 10x more awesome than the last one and
people will switch.
Also, GAP3 was a mature system, Sage is not. I think we should build the
system before thinking about maintaining bug-by-bug backward compatibility.
> Overall: I am all for removing cruft, but given that we deprecated
> less than 10 functions over the last 8 months or so this API cruft
> must not exist to the extend you claim. I talked to Burcin about this
> and he raised some concrete examples, but he might want to describe
> them since my recollection is hazy.
Think about e.g. the planed break up of gen.pyx into elements that make sense.
Maintaining bug-by-bug backward compatibility will be a nightmare because the
file is pretty messy. I'm sure one can do all kind of weird things with
gen.pyx right now that one shouldn't be able to do. Shall we keep this
functionality for backward compatibility?
Cheers,
Martin
--
name: Martin Albrecht
_pgp: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x8EF0DC99
_otr: 47F43D1A 5D68C36F 468BAEBA 640E8856 D7951CCF
_www: http://www.informatik.uni-bremen.de/~malb
_jab: martinr...@jabber.ccc.de
I am pretty sure it will have an impact on user's code because it is supposed
to clean up the mess that is gen.pyx. Maintaining that interface would defeat
the purpose of the break up in the first place. On the other hand, maybe
that's not what Craig and Robert have in mind anwyay.
> > Maintaining bug-by-bug backward compatibility will be a nightmare because
> > the file is pretty messy. I'm sure one can do all kind of weird things
> > with gen.pyx right now that one shouldn't be able to do. Shall we keep
> > this functionality for backward compatibility?
>
> Probably not. But if someone knowingly or unknowingly abuses and
> interface code will break. Can you give an example of what you mean?
How do we define that someone 'abuses' a class when it is full of weird stuff
(e.g. stuff to make things faster before proper code was written etc.) That
kind of stuff has to go because it encourages bad code to be written.
> I don't mean this in a negative way, I am truly curious :). I know that
> gen.pyx could certainly use a spring cleaning and that in general as
> the coverage creeps up we will encounter all kinds of bad code that
> has been around for a while and no one has touched it. Sage must also
> be made more consistent and in the process we will have to break some
> things - this is unavoidable. It would be nice if we had something
> like a major version jump to clearly indicate the before and after,
> but it seems that this will be hard to accomplish consistently.
The major version jump is *exactly* what I've been lobbying for since SD12 :)
If we can't manage to pull this one off, then at least we should have a
section in the release notes: this and that behavior was changed and might
affect your code. Also, if we can we add deprecation warnings (and eventually
we kill the code if it causes hassles)?
Cheers,
Martin
--
name: Martin Albrecht
_pgp: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x8EF0DC99
_otr: 47F43D1A 5D68C36F 468BAEBA 640E8856 D7951CCF
_www: http://www.informatik.uni-bremen.de/~malb
_jab: martinr...@jabber.ccc.de
You have been using Sage for about a year now, or more. In your
opinion, how are we doing so far regarding breaking or not breaking
*your* code with each new release of Sage? When your code does break,
how responsive have we been.
-- William
Since you claim to be obnoxious, perhaps you could ping the list if
you see a message
that has sat there unanswered for a while. :-)
William
+1 as well for exactly the reasons that Robert gave. If we do this, I
think we ought to heavily market the shift-tab functionality.
Jason
While this thread has gone off into deep waters, on this specific issue,
I don't see a problem with having both right_kernel and kernel_right, as
it is just an alias (or, given the problems that Nick Alexander points
out with aliases and subclassing, maybe a function which immediately
calls another function).
That said, if we'd like to eventually reduce namespace clutter (e.g.,
1-2 years), then I don't see the harm in doing what another person
suggested: remove kernel_right from the tab-completion list. That will
hide it so that (most) people won't write code using it, which cuts down
on the number of breakages in several years.
For what it's worth, the namespace clutter I was really thinking of
addressing was *future* clutter, not necessarily removing existing aliases.
Anyways, back to the regularly scheduled rants... :)
Jason
Of course, those using Thunderbird or another (ahem, "proper" :)
newsreader with the gmane interface can easily see threads with only one
message.
(/me wonders if I just volunteered to answer every orphaned message ever :).
Jason
Note that this suggestion won't work on the command line.
Carl
Since it's tricky, do you want to do this?
Does anyone know off the top of their head how to do something like this
in ipython?
Jason
Hmm... I was guessing that xterm had no way to pass a "shift-tab" to
an application, but actually it looks like I was wrong; it works for
Emacs, so it presumably works (or could work) for Sage. xterm sends
ESC [ Z
I have no idea how hard it would be to actually catch that. (In the
worst case, I could imagine that we would have to modify both readline
and IPython.)
I also don't know what other terminal emulators besides xterm do.
Carl
Set up a new newsgroup account in Thunderbird. The server will be
news.gmane.org. Once you have the account in thunderbird set up, do
"Manage newsgroup subscriptions". You want newsgroup
gmane.comp.mathematics.sage.devel.
Let me know if you need more info.
Jason
+1 as well
And a big +1 in general for this discussion. In MuPAD-Combinat we had
gone for the "eigenvectors_right" convention precisely for this
question of tab completion. When moving to sage, we discovered the
bla.*eigenvectors*? trick, and decided accordingly to drop the ugly.
Note: to me the most natural thing to do would be (and this would be
consistent with "?"):
FOO.X<TAB>: current behavior: searches for attributes that start with X
FOO.*X<TAB>: extended behavior: searches for attributes that contain X
One advantage is that this should require no change in the sage
interfaces. In particular, this does not require playing with special
inputs like Shift-TAB, which can be messy in terminals.
Cheers,
Nicolas
--
Nicolas M. Thiéry "Isil" <nth...@users.sf.net>
http://Nicolas.Thiery.name/
One disadvantage of this is that if one types Foo.X<tab> and doesn't
see the command one wants, one has to go all the way back and insert
the * rather than doing shift-tab at that point to get more options.
I'm not trying to mitigate the terminal issues though, no reason we
can't provide both options.
Also, I am +1 for the idea of removing deprecated functionality from
the tab completion lists too.
- Robert
Yes, in Sage there was a lot of discussion and it was decided that
default implementations of algorithms should always be "proof=True",
unless it is crystal clear from the function name (e.g.,
next_pseudoprime).
<rant> The Singular documentation -- and me the authors of Singular
(?) -- seem to claim that they have implemented an algorithm that is
supposed to give a provably correct result. But it's not only not
"provable correct", it's frequently not correct at all. </rant>
-- William
I actually like this perhaps a bit better, easier to type and to
remember. It is also more likely to be "discovered."
- Robert
iPython, by default, lists all possible completions when the TAB key
(or Ctrl-l) is pressed. But this behaviour can be changed (via the
user's personal ipythonrc file) to: TAB completes, but does not show
completions; TAB-TAB shows completions.
I guess I wanted to point out that:
(1) With a special, non-default setting in iPython, TAB-TAB has some
significance.
(2) The fact that iPython already has a mechanism to detect and handle
two TAB keypresses should make implementation easier.
If we decided to implement Simon's suggestion (which I like), we
should keep the first issue in mind. Perhaps that behaviour can be
relegated to TAB-TAB-TAB? (If the option is set, then: TAB completes,
but does not show completions; TAB-TAB shows completions; TAB-TAB-TAB
shows all completions containing ....)
Take care,
Franco
--