Dim Byref syntax
Re: Dim Byref syntax
BTW does a null reference have to be deleted explicitly?
Re: Dim Byref syntax
No, as for a null pointer, but deleting it is still an allowed syntax (inducing no action).
Re: Dim Byref syntax
So I noticed, thanks.fxm wrote:No, as for a null pointer, but deleting it is still an allowed syntax (inducing no action).
Re: Dim Byref syntax
In general you only need to delete objects you allocated on the Heap, with "new", "allocate", malloc(), etc.
Objects stored on the stack or in a data segment of the application do not need to be deleted.
Objects stored on the stack or in a data segment of the application do not need to be deleted.
Re: Dim Byref syntax
While it is possible via a Define construct to create an object with null reference within an object, it appears FB insists on creating the object before the (default) constructor is invoked. The following code compiles, but execution raises a segmentation fault. When commenting out object 'a' in 'tt' it runs fine.
Code: Select all
#define nilref(o) *cptr(o ptr, 0)
#define nilobj(o) o = nilref(o)
#define obj(o) byref o
#define ref(o) @(o)
type ta extends object
s as string
end type
type tt extends object
s as string
a as nilobj(ta)
end type
dim obj(t) as nilobj(tt)
print "new reference:"
ref(t) = ref(tt())
Re: Dim Byref syntax
More simply, this obviously crashes:
while it normally works:
Code: Select all
Dim As Integer I = *Cptr(Integer Ptr, 0)
Print "NOK"
Sleep
Code: Select all
Dim Byref As Integer RI = *Cptr(Integer Ptr, 0)
Print "OK"
Sleep
Re: Dim Byref syntax
Yes it is the BYREF cake that must be eaten. ;-) Ideally this would work, but it doesn't:
This code compiles but it doesn't run. object 'a' doesn't seem to be recognized as such because any reference (@) fails.
Code: Select all
#define unref(o) delete @(o)
#define newobj *new
#define nil(o) @(o) = 0
#define nilref(o) *cptr(o ptr, 0)
#define nilobj(o) o = nilref(o)
#define obj(o) byref o
#define ref(o) @(o)
type ta extends object
s as string
end type
type tt extends object
s as string
a as nilobj(ta)
declare constructor()
declare destructor()
end type
constructor tt()
a = newobj ta
end constructor
destructor tt()
a = nilref(ta)
end destructor
function InitTT(s as string) byref as tt
if len(s) then
dim obj(res) as tt = newobj tt()
res.s = s
return res
end if
return nilref(tt)
end function
dim obj(t) as nilobj(tt)
ref(t) = ref(InitTT("Hello world!"))
if not nil(t) then
print t.s
unref(t)
else
print "no ref"
end if
Re: Dim Byref syntax
Interestingly, nested objects that obviously are not created BYREF, do accept a new instance from a byref function result, which makes these kind of function constructs definitely valuable:
Code: Select all
#define unref(o) delete @(o)
#define newobj *new
#define nil(o) @(o) = 0
#define nilref(o) *cptr(o ptr, 0)
#define nilobj(o) o = nilref(o)
#define obj(o) byref o
#define ref(o) @(o)
type ta extends object
s as string
end type
type tt extends object
s as string
a as ta
declare constructor()
end type
declare function InitTA(s as string) byref as ta
declare function InitTT(s as string) byref as tt
dim obj(t) as nilobj(tt)
ref(t) = ref(InitTT("Hello world!"))
if not nil(t) then
print t.s
print t.a.s
'unref(t)
else
print "no ref"
end if
end
constructor tt()
'a = newobj ta
a = InitTA("ok")
end constructor
function InitTA(s as string) byref as ta
if len(s) then
dim obj(res) as ta = newobj ta()
res.s = s
return res
end if
return nilref(ta)
end function
function InitTT(s as string) byref as tt
if len(s) then
dim obj(res) as tt = newobj tt()
res.s = s
return res
end if
return nilref(tt)
end function
Re: Dim Byref syntax
But in the constructor, if 'a' gets assigned a null reference because the string passed is empty, a segmentation fault is raised upon the assignment. This can be solved by first creating a new null reference for 'a'. Comment out the dim statement in the constructor to see the difference.
Code: Select all
#define unref(o) delete @(o)
#define newobj *new
#define nil(o) @(o) = 0
#define nilref(o) *cptr(o ptr, 0)
#define nilobj(o) o = nilref(o)
#define obj(o) byref o
#define ref(o) @(o)
type ta extends object
s as string
end type
type tt extends object
s as string
a as ta
declare constructor()
end type
declare function InitTA(s as string) byref as ta
declare function InitTT(s as string) byref as tt
dim obj(t) as nilobj(tt)
ref(t) = ref(InitTT("Hello world!"))
if not nil(t) then
print t.s
'print t.a.s
'unref(t)
else
print "no ref"
end if
end
constructor tt()
' make a new nil object
dim obj(a) as nilobj(ta)
ref(a) = ref(InitTA(""))
end constructor
function InitTA(s as string) byref as ta
if len(s) then
dim obj(res) as ta = newobj ta()
res.s = s
return res
end if
return nilref(ta)
end function
function InitTT(s as string) byref as tt
if len(s) then
dim obj(res) as tt = newobj tt()
res.s = s
return res
end if
return nilref(tt)
end function
Re: Dim Byref syntax
OK, nice fooling myself. The dimmed object 'a' inside the constructor is seen as a new local object, which is destroyed at the end of the constructor.
Bottomline, avoid null references of nested objects, NOT just inside constructors! What can be done is a new reference of a nested object with the NEW keyword, but a subsequent DELETE is also not allowed.
Bottomline, avoid null references of nested objects, NOT just inside constructors! What can be done is a new reference of a nested object with the NEW keyword, but a subsequent DELETE is also not allowed.
Re: Dim Byref syntax
I think the main idea of references is that they always actually refer to something valid. I think references can be reassigned; it's just the assignment syntax that needs to clear; either assigning the value or rebinding the reference.
Here's a different approach:
EDIT:
The extra check for "Nothing" is due to a bug in 1.05. For the example, in 1.06, can use:
If a reference always points to something valid, there's no need for null pointer checks on every use.
Here's a different approach:
Code: Select all
type NothingObject extends object
end type
dim shared Nothing as NothingObject
function IsNothing( byref obj as object ) as boolean
function = ( obj is NothingObject )
end function
'' maybe a 'set variable = object' syntax? like from VB?
#macro set_obj( x, expr )
'' careful, this macro is case sensitive
#if #expr = "Nothing"
@x = @Nothing
#else
'' never assign zero address
if( @expr ) then
@x = @expr
else
@x = @Nothing
end if
#endif
#endmacro
#define identify( x ) _
iif( x is NothingObject, "Nothing", "Something" )
type T extends object
end type
dim obj as T
dim byref ref as object = Nothing
print "ref is " & identify( ref )
set_obj( ref, obj )
print "ref is " & identify( ref )
set_obj( ref, Nothing )
print "ref is " & identify( ref )
set_obj( ref, obj )
print "ref is " & identify( ref )
dim byref NullRef as object = *cptr(object ptr, 0)
set_obj( ref, NullRef )
print "ref is " & identify( ref )
The extra check for "Nothing" is due to a bug in 1.05. For the example, in 1.06, can use:
Code: Select all
'' maybe a 'set variable = object' syntax?
#macro set_obj( x, expr )
'' Never set a zero value
if( @expr ) then
@x = @expr
else
@x = @Nothing
end if
#endmacro
Re: Dim Byref syntax
Can you recall more precisely the fix and the corresponding sentence in changelog.txt?coderJeff wrote: EDIT:
The extra check for "Nothing" is due to a bug in 1.05. For the example, in 1.06, can use: ...
Re: Dim Byref syntax
There is a price for that philosophy: inefficiency. Objects are created before the programmer has a choice what to assign (usually different types of constructors with specific parameters). So way too often a new copy is made always leaving something in memory even if there is no need to. From my RealBASIC experience I know how valuable null objects are. Granted, early on I had a lot of Nil Object exceptions because with QuickBASIC as background I thought of classes/objects as simple Type structures that were automatically assigned. Here is a RealBASIC example that demonstrates the usefulness of null objects:coderJeff wrote:I think the main idea of references is that they always actually refer to something valid.
Code: Select all
' create instance immediately (but is it necessary?)
dim f as FolderItem = new FolderItem()
' declare object but no instance yet (null object)
dim f as FolderItem
' call file open dialog
f = GetOpenFolderItem()
if f <> nil then
' user selected a file
' ...
end if
' If the user did not select a file, we have no use for an instance...
In my years long experience with RealBASIC I found only two logical places where objects could be null; that's 1. in the constructor where nested objects HAD to be instantiated explicitly, and 2. in procedures where local instances were created. In either case the programmer had full control over references. When programmed logically one never had to check several times if a reference was actually there. Only when calling specific functions that could fail, a nil object could be returned. Usually a try..except..finally block was part of such code parts.coderJeff wrote:If a reference always points to something valid, there's no need for null pointer checks on every use.
The idea of the NEW keyword in general is to create an instance of an object. Currently I have to declare and assign an object in one go in order to avoid two constructor calls:
Code: Select all
dim s as SomeObject = SomeObject()
I believe the main issue with FB is that it initially is based on the procedural programming legacy of the 80s and 90s, most notably QuickBASIC. A compiler designed for OOP from scratch usually has a very different and more efficient approach with object handling. In the case of FB the introduction of the keyword CLASS could have separated such implementation from Types, making things less complicated.
However I do believe that FB has come a long way and that its attempt to support full OOP is admirable. But it could be implemented with more efficiency and programmer choosing in mind.
Re: Dim Byref syntax
I don't understand:Munair wrote:Currently I have to declare and assign an object in one go in order to avoid two constructor calls:Code: Select all
dim s as SomeObject = SomeObject()
dim s as SomeObject
calls implicitly the default constructor (which exists because the below syntax rightly compiles),
while:
dim s as SomeObject = SomeObject()
calls explicitly the default constructor,
but the two generated codes are identical.
Re: Dim Byref syntax
In this case, yes, but if I need to call a different constructor later on with a parameter which value is not known yet, or assign the object to the result of a function, I am still left with a full instance for which I may have no use. This is why in RealBASIC every (nested) object had to be instantiated explicitly, because there was no telling when and how the object should be instantiated.fxm wrote:I don't understand:
dim s as SomeObject
calls implicitly the default constructor (which exists because the below syntax rightly compiles),
while:
dim s as SomeObject = SomeObject()
calls explicitly the default constructor,
but the two generated codes are identical.
Last edited by Munair on Nov 27, 2018 8:36, edited 1 time in total.