Why cannot we have our cake and eat it too?

Isn't there a way to have the import/export classes in 
a separate file that gets imported  inside an import/export 
alias in the graph class so that
G.export
is actually GraphExporter(G, whatever) and tab 
completion works?

Partially related, ticket #9731 [1] might be relevant.
http://trac.sagemath.org/sage_trac/ticket/9731 

Cheers,
J


On Monday, July 9, 2012 4:03:55 AM UTC+1, Dima Pasechnik wrote:
>
>
>
> On Monday, 9 July 2012 10:22:31 UTC+8, Birk Eisermann wrote:
>>
>> Hello!! 
>>
>> What is your opinion about improving the export and import of graphs? 
>>
>> My conclusion of the sage-devel thread "Code duplication and aliases in 
>> methods" is that at the moment the source code in graph theory is not so 
>> optimal organized. As promised, I want to show some modifications that 
>> would lead to a better design. 
>>
>> I found following members dealing with import or export of the class 
>> Graph. 
>>
>> - returning a string to represent a graph: 
>> g.graph6_string, g.graphviz_string, g.dumps 
>>
>> - export of a graph to a file 
>> g.graphviz_to_file_named, g.dump, g.save, g.db, (g.write_to_eps seems to 
>> involve g.plot) 
>>
>> - import of a graph from a file 
>> none found??  Oh, they are hidden in the class constructors!! 
>>
>>
>> Including this functionality into the class Graph makes this class 
>> heavier and more difficult to understand - in my opinion (see the 
>> "single responsibility principle" [1]). Hence, I would create two 
>> separate classes for that. 
>
>
> this sacrifices a very important in interactive use feature: currently one 
> can create 
> an instance G of Graph and then 
>
> sage: G.<hit 'Tab'>
>
> to see the methods of G. I understand that you are coming from a C++ 
> background where nothing like this is possible at all, but this is a very 
> quick and efficient way of looking up documentation without opening the 
> manual.
>
> Removing methods from Graph is removing them from this list of completions.
> Ideally, as there are indeed too many methods in Graph, one might rather 
> think of having nested classes; then
>  sage: G.<hit 'Tab'>
> would only show subclasses and immediate members:
>
> sage: class A:
> ....:     x=1
> ....:     class B:
> ....:         y=2
> ....:         
> sage: a=A()
> sage: a.   # Tab was hit here
> a.B  a.x  
> sage: a.B.y  # Tab was hit here, and produced unique completion, y
>
> Dima
>
>  
>
>> Actually, there is no need to have pairs of 
>> import/export functions. Maybe one wants to read some special format 
>> only but does not need to write in that format. Or vice verse. Hence, I 
>> separate the import functions from the export ones. 
>>
>> My approach uses static classes, that is, they contain no data and only 
>> member functions. For every programming task, there is only one instance 
>> which exports the graphs (and one for importing). Since we have two 
>> different types of graphs, Graph and Digraph, we need some case 
>> distinction... 
>>
>> Some pseudo code about the classes - just to get the idea - hope you can 
>> understand :-) 
>>
>> {{{ 
>> def GraphExporter: 
>>      def graphviz(graph_object, filename, more_options)  # calls 
>>                                  helper functions according to type 
>>      def _graphviz_Graph(graph_object, filename, more_options) 
>>      def _graphviz_DiGraph(graph_object, filename, more_options) 
>>
>>      def sage_format(graph_object, filename, more_options)  # calls 
>>                                  helper functions according to type 
>>      def _sage_format_Graph(graph_object, filename, more_options) 
>>      def _sage_format_DiGraph(graph_object, filename, more_options) 
>>
>>      def graph6_string(graph_object) returns string 
>>      def graphviz_string(graph_object) returns string 
>>
>> def GraphImporter: 
>>      def graphviz(filename, more_options) returns Graph_or_DiGraph_object 
>>      def graphviz_get_type(filename, more_options) returns graph_type 
>>      def _graphviz_Graph(filename, more_options) returns Graph_object 
>>      def _graphviz_DiGraph(filename, more_options) returns DiGraph_object 
>>
>>      def sage_format(filename, more_options) returns (Di)Graph_object 
>>      def sage_format_get_type(filename, more_options) returns graph_type 
>>      def _sage_format_Graph(filename, more_options) returns Graph_object 
>>      def _sage_format_DiGraph(filename, more_options) returns 
>> DiGraph_object 
>>
>>      def graph6_string(string) returns graph_object 
>>      def graphviz_string(string) returns graph_object 
>> }}} 
>>
>> Advantages of this design: 
>> + Adding a new import or export format is easier since the class 
>> Graph/DiGraph will not be touched. 
>> + The classes Graph and DiGraph will have less members. Files like 
>> graph.py and digraph.py will slightly lose weight... 
>>
>> Disadvantage(s): 
>> - There is one more file and two more classes..., Anything else? 
>>
>>
>> Example code for reading unknown file and then write it in another 
>> format: 
>> {{{ 
>>     GI = GraphImporter() 
>>     G = GI.graphviz("/home/sage/myfile.viz") 
>>     GraphExporter().sage_format(G, "/home/sage/myfile.sage") 
>> }}} 
>>
>> What do you think about this approach? I might have overseen things 
>> since I am quite new to sage... 
>>
>> Birk 
>>
>> [1] https://en.wikipedia.org/wiki/Single_responsibility_principle 
>>
>

-- 
-- 
To post to this group, send an email to sage-devel@googlegroups.com
To unsubscribe from this group, send an email to 
sage-devel+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/sage-devel
URL: http://www.sagemath.org

Reply via email to