[Gambas-user] a few suggestions for improvement

Benoit Minisini gambas at ...1...
Wed Jan 5 16:46:00 CET 2005


On Wednesday 05 January 2005 15:24, Toni Schornboeck wrote:
> Hello Folks.

Hello,

>
> First I want to say that I like the Gambas Environment very much.
> But there are a few things that I don't like.
> I want to explain what I don't like, why and how it could be improved.
> I would be glad if you could answer me and discuss my proposals.
>
>
> After a Form is closed, the object still lives, but at the same time is
> dead.
> I'd like to write code like:
> dim f as Form
> f=new Form(foo)
> f.ShowModal()
> return f.Result
>
> or something like that. But it is not possible, because f dies after
> "ShowModal()"
> I think that is unecessary. f should stay alive until it gets out of scope.
> It would be OK, if a closed form can never be opened again, therefore a
> f.ShowModal()
> f.ShowModal()
> could raise an error.
>
> Take for example a InputBox. AFAIK the currently best solution is:
> static public function Run() as String
>  dim f as InputBox
>  f=new InputBox
>  f.ShowModal()
>  return value
> end
>
> private static value as String
>
> public sub Form_Close()
>  value=Text1.Text
> end
>
> This Solution is just Plain ugly and can lead to Bugs, when 2 InputBoxes
> are open at the same time.

Well, I dont find that ugly, and if you have several instances of your form, 
just don't declare the variable static.

>
>
>
> A constructor has always to be public. Why?

It is by design.

> I'd like to declare a constructor private to force the user of my code to
> use a static
> construct (that means: a static function that returns the object).
> This can sometimes be useful, for example when using a factory to prohibit
> the user from directly instanciating
> objects.
>

At the moment, I don't see any mean to do that cleanly.

>
> This leads to another point: friends could be useful or something like Java
> Packages where one can declare a method
> as package private.
>

In Gambas, public means exported. If something is private in a class, then the 
interpreter can't access it from outside the class. So, constructors, 
destructors, event handlers... need to be public, or the interpreter won't be 
able to call them.

>
> optional parameters are very useful, but why can I only assign a default
> value to primitive types?
> private sub foo(optional i as integer = -1)
> is perfectly legal, but
> private sub foo(optional o as Bar=new Bar(baz))
> is rejected :(
> It would be nice to define default values also for objects.

I think it is just something to change in the compiler. So it may be 
possible :-)

>
> The workaround using
> if isnull(o) then o=new Bar(baz)
> doesn't always work.
> Because NULL may be a perfectly legal value in some cases.
>
>

Well, in your example, NEW will never return NULL.

>
> for each on collections acts weird.
> for each v in col
>  print col.Key & "=" & v
> next
> This looks ugly. col is changed even though I don't write to it, but just
> read values from it.
> And it isn't really intuitive to look for key in col...

I don't unserstand what you say. Collection.Key is just a read-only property 
that returns the key of the last entry accessed in the collection. I don't 
see where the collection is modified during the iteration...

>
> It would be nice if we could introduce an iterator concept.
> But this is quite controversal, so I would like to get your opinion first,
> before thinking
> too far.
>

A class can have a '_next' method to implement iteration. But only a native 
class (written in C/C++) can use that.

>
>
> I really miss a 'super' or 'base' keyword to access the Baseclass from
> within the derived class.
> In my current work I have this Code:
> PUBLIC FUNCTION doGetQuery() AS SelectQuery
>  DIM query AS SelectQuery
>  DIM super AS DependentDataSource
>
>  IF IsNull($con.Value()) THEN RETURN NULL
>
>  super=ME
>  query=super.doGetQuery()
>  query.AddWhere($field & "='" & CStr($con.Value()) & "'")
>
>  RETURN query
> END
>
> DependentDataSource is the Baseclass.
> I have to do an upcast (without casting operators, I'll talk about them a
> bit later) to access
> doGetQuery() of the base class.
> It would be much nicer if I could simply write
> SUPER.doGetQuery()
>

You are right, SUPER is missing. It's in my TODO list.

>
>
> This leads to another point:
> Why can't I define which parameter are passed to my base class?
> Take for example a XML Parser. There are a few Node classes, all derived
> from BaseNode.
> Every Node contains an array of allowed child nodes.
> One could write:
> SomeNode.class:
> public sub _new()
>  'call base constructor
>  super(allowedChildren)
> end
>
> but currently this isn't possible because the user has to specify the
> params.
> but in this code only the class itself knows which child nodes are allowed
> and the user
> shouldn't care.
>
> The workaround using set-Methods to set the allowed children afterwards is
> not perfect, because
> the child nodes should be set exactly once when the object is instaciated
> and shouldn't change
> later.
>

Try that:

BaseNode.class:

PUBLIC SUB _new()
...
END

SomeNode.class:

PUBLIC SUB _new(allowedChildren)
...
END

Each class in the inheritance hierarchy consumes the parameters passed to the 
constructor. 

>
>
> I already mentioned the lack of casting Operators.
> Take for example another code from my current work (stripped down):
>  DIM control AS Control
>
>  SELECT CASE type
>    CASE "select"
>      control=NEW ComboBox(detailFrame) AS "EditControls"
>      Object.SetProperty(control, "ReadOnly", TRUE)
>  END SELECT
>
> this factory creates a control depending upon a parameter.
> It has to set a few parameters, like ReadOnly=TRUE
> It would be nice if I could write:
> ((ComboBox)control).ReadOnly=TRUE
> or
> Cast(ComboBox, control).ReadOnly = TRUE
> or something like that.

If I remember, you can do ComboBox(...) to cast to ComboBox. Test it to see if 
it really works.

>
> If I could declare variables everywhere I like would also help.
>
>
> This leads to: variables must be declared at begin of function
> why is that?
>
> In C it was a pain in the ass, so they removed this restriction with C99
> and no other major language hast
> that restriction. Even VB doesn't ;)

I find declaring variable everywhere a source of confusion and unreadable 
code. So I force them to be declared at the beginning of the function. And 
one by line at the moment ?

>
> It would be really important to allow the user to declare variables as
> local as possible.
> it is even more important because gambas functions tend to be bigger than
> for example Java or C++ functions
> (my own personal expierence)
>

You are not compelled to write large functions...

>
>
> A very controversal point is:
> no RETURN will return NULL
> I'd prefer a warning when I forgot to write a return statement within a
> function.

It is by design.

>
>
>
> One thing that really annoys me is:
> arr.Add(new Foo(bar))
> doesn't work.
>
> I have to write
> dim t as Foo
>
> t=new Foo(bar)
> arr.Add(t)
>
> I worked around it by providing a static public make function:
> static public make(p as Bar)
>  dim obj as Foo
>  obj = new Foo(p)
>  return obj
> end
> so I can write
> arr.Add(Foo.make(bar))
>
> but it would be nice if I could simply write new Foo everywhere where I can
> put a Foo object.
>

It is by design too. I didn't want to make NEW a true operator. But it is just 
a compiler restriction. The interpreter don't care.

For example, you can do

arr.Add(New("Foo", bar))

>
>
> another nice feature would be, if one could declare a variable inside a for
> statement:
>
> for i as integer = 0 to 10
>
> i would be accessably only within the for loop
> this would be very convenient. it would also help to hold variables as
> local as possible.
> one normally uses a loop variable i just for looping and nothing more so it
> would be really nice if one
> could express the use of i this strong and obvious.
>

Same remark than before. And I don't see the benefit of having variables "as 
local as possible". It will change nothing in interpreted code.

>
>
> Why doesn't gambas do virtual dispatching?
> I have a base class called Base and a derived class called Derived.
> bot implement the method GetQuery()
>
> When I have a reference to Base (which really is a reference to Derived,
> but was upcast)
> and call GetQuery() it will call Base's GetQuery instead of Derived's one.
>
> I have to use
> Object.Call(obj, "GetQuery")
> but this isn't so nice.
>
> So I worked around it by implementing GetQuery only in Base which looks
> like:
> public function GetQuery() as Foo
>  return Object.Call(ME, "doGetQuery")
> end
>
> Derived and Base implement also doGetQuery which does the actual work.
> But the drawback is: doGetQuery can't be private, because Object.Call
> wouldn't have access to it...
>
> I would like to see virtual dispatching in gambas improved, because
> currently it is (IMHO) a mess.
>

You are absolutely right. I just change the interpreter in the 2.0 so that 
virtual dispatching work. As soon as I release the first developmement 
version (1.9.1), you will be able to test it and tell me if things are right.

>
>
> The next issues are about the IDE gambas:
> I'd love to see the possibility to set the Tabstop ordering.
> currently I have to edit the *.form files and reorder the components. that
> could be improved!

TabOrder = ZOrder, so you just have to modify the second to change the first.

>
>
>
> It would improve the usability of the IDE if I could create directories to
> store my class and form files
> currently I have about 30 *.call files. conceptional there are 3 modules.
> if i could store them in 3 directories
> it would improve the management of them a lot.
>

I was thinking of letting the IDE show an ordered and hierarchical view of 
forms, classes and modules, even if they are stored flat in the project 
directory.

>
> a minor issue: the executale file of my project contains a lot of
> information that shouldn't be there
> for example:
>
> Project=ReportGenerator
> Title=ReportGenerator
> Startup=Report
> TabSize=2
> Argument=-h localhost -l schorny -p <snip> -n akademie
> Version=0.0.16
> Library=gb.db
> Library=gb.xml.libxml
> SnapToGrid=1
> ShowGrid=1
> Snap=8
> Localize=0
> KeepDebugInfo=0
> ControlPublic=0
> ExecPath=/home/schorny/code/ReportGenerator/report
> Prefix=0
>
> I think most of them are unecessary. And "Argument" is a bit dangerous - it
> contains the params that the IDE should use when
> calling the program. as you can see: it contains the login information for
> my test db. I don't want to give them to every user ;)
>

Well. It is a point I didn't think about :-) I note it in the TODO list.

>
>
> even though if have postet a lot of critic: I like gambas.
> Otherwise I wouldn't have convinced my boss to use Gambas for our Linux
> Clients ;)
>
> currently the best RAD environment for Linux/KDE -> congratulations!

Thank you!

Regards,

-- 
Benoit Minisini
mailto:gambas at ...1...




More information about the User mailing list