A strange __set() disturbance Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: A strange __set() disturbance

08 Aug 2020, 20:40

@swagfag
Over or under - life’s greatest question haha
User avatar
FredOoo
Posts: 186
Joined: 07 May 2019, 21:58
Location: Paris

Re: A strange __set() disturbance

09 Aug 2020, 01:20

VB and Java are just examples. I don't look at my navel. Calm down swagfag, it's just a talk.

Exercice to write .defineProp( name, { get: …/…, set: …/… } ):

Code: Select all

global gsProp_value := "UNSET"

class CF7 {
	__get( name, Params ){
		this.createProp( name )
		return this.%name%
	}
	__set( name, Params, value ){
		this.createProp( name )
	}
	createProp( name ){
		print "`n--- CreateProp: " name
		this.defineProp( name, {
	        get: objBindMethod( this, 'gsProp' ),
	        set: objBindMethod( this, 'gsProp' )
	    } )
	}
	gsProp( objThis, value:= unset ){
		;print " -- gsProp:", objThis, ", ", (isSet(value)?value:"UNSET")
		if isSet( value )
			gsProp_value := value
		else
			return gsProp_value
	}
}

F7 := CF7.new()
; --- CreateProp: anyname
print "F7.anyname: "   F7.anyname          ; UNSET
print "F7.anyname := " F7.anyname := 111   ; 111
print "F7.anyname: "   F7.anyname          ; 111
; --- CreateProp: another
print "F7.another: "   F7.another          ; UNSET
print "F7.another := " F7.another := 222   ; 222
print "F7.another: "   F7.another          ; 222
print
print "F7.anyname: "   F7.anyname          ; 222  ; Wrong of course because all are saved in one global variable

Exercice to save each property's value under its name:

Code: Select all

class CF8 {
	__new(){
		this.defineProp( 'PROPS', { value: Map() } )
	}
	__get( name, Params ){
		this.createProp( name )
		return this.%name%
	}
	__set( name, Params, value ){
		this.createProp( name )
		this.%name% := value  ; No need
	}
	createProp( name ){
		print "`n--- CreateProp: " name
		this.PROPS[ name ] := "UNSET"
		this.defineProp( name, {
	        get: ObjBindMethod( this, 'gsProp' ).bind( name ),
	        set: ObjBindMethod( this, 'gsProp' ).bind( name )
	    } )
	}
	gsProp( name, objThis, value:=unset ){
		;print " -- gsProp:", name, ", ", objThis, ", ", (isSet(value)?value:"UNSET")
		if isSet( value )
			objThis.PROPS[ name ] := value
		else
			return objThis.PROPS[ name ]
	}
}
; And I don't use Params yet.

F8 := CF8.new()
; --- CreateProp: anyname
print "F8.anyname: "   F8.anyname          ; UNSET
print "F8.anyname := " F8.anyname := 111   ; 111
print "F8.anyname: "   F8.anyname          ; 111
; --- CreateProp: another
print "F8.another: "   F8.another          ; UNSET
print "F8.another := " F8.another := 222   ; 222
print "F8.another: "   F8.another          ; 222
print
print "F8.anyname: "   F8.anyname          ; 111

Simplification exercise:

Code: Select all

class CF9 {
	__get( name, Params ){
		return "UNSET"
	}
}

F9 := CF9.new()
print "F9.anyname: "   F9.anyname          ; UNSET
print "F9.anyname := " F9.anyname := 111   ; 111
print "F9.anyname: "   F9.anyname          ; 111
print
print "F9.another: "   F9.another          ; UNSET
print "F9.another := " F9.another := 222   ; 222
print "F9.another: "   F9.another          ; 222
print
print "F9.anyname: "   F9.anyname          ; 111
print
print "F9.parametred := ",    F9.parametred := []        
print "F9.parametred[1] := ", F9.parametred.push( 11 ) 
print "F9.parametred[2] := ", F9.parametred.push( 22 ) 
print "F9.parametred: ",      F9.parametred            ; [ 11, 22,  ]
print "F9.parametred[1]: ",   F9.parametred[1]         ; 11
print "F9.parametred[2]: ",   F9.parametred[2]         ; 22
  
Is that correct ?
print.ahk
Last edited by FredOoo on 09 Aug 2020, 22:23, edited 1 time in total.
(Alan Turing) « What would be the point of saying that A = B if it was really the same thing? »
(Albert Camus) « Misnaming things is to add to the misfortunes of the world. »
User avatar
FredOoo
Posts: 186
Joined: 07 May 2019, 21:58
Location: Paris

Re: A strange __set() disturbance

09 Aug 2020, 04:52

Exercice using one parameter as a key :

Code: Select all

class CF10 {
	__new(){
		this.defineProp( 'PROPS', { value: Map() } )
	}
	__get( name, Params ){
		this.createProp( name )
		key := Params[1]
		return this.%name%[key]
	}
	__set( name, Params, value ){
		this.createProp( name )
		key := Params[1]
		this.%name%[key] := value  ; Need
	}
	createProp( name ){
		print "`n--- CreateProp: " name
		this.PROPS[ name ] := Map()
		this.defineProp( name, {
	        get: objBindMethod( this, 'gsProp' ).bind( name ),
	        set: objBindMethod( this, 'gsProp' ).bind( name )
	    } )
	}
	gsProp( name, objThis, key, value:=unset ){
		;print " -- gsProp:", name, ", ", objThis, ", ", key, ", ", (isSet(value)?value:"UNSET")
		if isSet( value ){  ;set
			(objThis.PROPS[ name ])[value] := key  ; VERY STRANGE ORDER value/key
		}else{  ;get
			try
				return (objThis.PROPS[ name ])[key]
			catch
				return 'UNSET'
		}
	}
}

F10 := CF10.new()
; --- CreateProp: anyname
print "F10.anyname[1]: "   F10.anyname[1]          ; UNSET
print "F10.anyname[1] := " F10.anyname[1] := 101   ; 101
print "F10.anyname[1]: "   F10.anyname[1]          ; 101
print "F10.anyname[2] := " F10.anyname[2] := 102   ; 102
print "F10.anyname[2]: "   F10.anyname[2]          ; 102
; --- CreateProp: another
print "F10.another[1]: "   F10.another[1]          ; UNSET
print "F10.another[1] := " F10.another[1] := 201   ; 201
print "F10.another[1]: "   F10.another[1]          ; 201
print "F10.another[2] := " F10.another[2] := 202   ; 202
print "F10.another[2]: "   F10.another[2]          ; 202
print
print "F10.anyname[1]: "   F10.anyname[1]          ; 101

Any criticism or improvement is welcome.
(Alan Turing) « What would be the point of saying that A = B if it was really the same thing? »
(Albert Camus) « Misnaming things is to add to the misfortunes of the world. »
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: A strange __set() disturbance

09 Aug 2020, 17:07

Exercice to write .defineProp( name, { get: …/…, set: …/… } ):

Code: Select all

...
	        get: objBindMethod( this, 'gsProp' ),
	        set: objBindMethod( this, 'gsProp' )
...
by using ObjBindMethod() here, uve created a circular reference, which means any instance of ur object wont ever get automatically deleted, unless u manually clear the reference(by redefining the Xetter or deleting the property altogether). its possible that in the context of ur script u dont have to care about undeletable objects, but its more probable that its an error that needs fixing. further, because uve used ObjBindMethod(), u had to write ur method signature like this gsProp( objThis, value:=unset ){, where you have once bound this to the method's implicit this(recall that any method signature actually looks like method(this, ...) { } under the hood) and the very next parameter to receive a value, receives the value of the very same instance that ure invoking the property on(in other words, this == objThis == F7).
use this.GetMethod('gsProp') and change ur signature to read gsProps(value := unset) {}, so u can avoid creating circular references and doubly retrieving references to the same object.

Code: Select all

print "F7.another: "   F7.another          ; UNSET
this is also ; Wrong of course because all are saved in one global variable, u overwrote the variable two lines ago
Exercice to save each property's value under its name:
its a contrived example, so i cant comment on whether to do X or not. if real-world code requires that u store them in a Map for whatever reason, as long as it works properly, do what u gotta do
Simplification exercise:

Code: Select all

class CF9 {
	__get( name, Params ){
		return "UNSET"
	}
}
Is that correct ?
yes
Exercice using one parameter as a key :

Code: Select all

...
		objThis.PROPS[ name ])[value] := key  ; VERY STRANGE ORDER value/key
...
that is weird, considering:
  • meta-set's signature is __Set(this, Name, Params, Value) { }
  • yet the set function object's appears to be ...(this, Value, Params*) { }
User avatar
FredOoo
Posts: 186
Joined: 07 May 2019, 21:58
Location: Paris

Re: A strange __set() disturbance

09 Aug 2020, 20:55

Previously I showed an example of a value property.
{value: theStoredValueOfProp} It's easy here.

With CF7 above, this is an example of a dynamic property.
{get: aFunctionCall, set: aFunctionCall}

The exercise consists in finding the syntax of the call and the signature of the called function. (Because the documentation is abstract. It explains things but does not show them in an example.)
The value of the property doesn't need to be stored (it can be recalculated on every call) that's why I neglect it completely (I store everything in a global variable, but it's just a step) .

The CF8 exercise is not just a contrived example. The defined properties must be recalled by their name. Here, the exercise is therefore to pass the name of the property in the parameters.

When for exercise CF7 you tell me to use get: this.GetMethod ('gsProp2'), you are right. It works.
However, it doesn't work at all in CF8 with get: this.GetMethod ('gsProp2').bind (name)
So we can no longer recall a property by name. it's still a shame.

This is where normally you should set the example yourself ...

Exercise CF9 contains a heresy because in AHK a variable should never be undefined. It would be better to write this:
class CF9 {
}

Then write directly in the properties. It works very well and that will probably be the conclusion of the topic.

As for the strange order of the value / key parameters, I believe it shows that a full and complete use of __get / __ set with property name, parameters and internal get / set definition, are not yet fully developed .
No one has shown me otherwise yet. My conclusion is that it is better not to use them.
(Alan Turing) « What would be the point of saying that A = B if it was really the same thing? »
(Albert Camus) « Misnaming things is to add to the misfortunes of the world. »
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: A strange __set() disturbance

10 Aug 2020, 00:06

that is weird, considering:
meta-set's signature is __Set(this, Name, Params, Value) { }
yet the set function object's appears to be ...(this, Value, Params*) { }
It is not a meta set being called. It is a prop setter.
defineprop wrote: Set: The function object to call when the property is assigned a value. Its second parameter is the value being assigned.
[...]
The MaxParams and IsVariadic properties of the function objects are evaluated to determine whether the property may accept parameters. If MaxParams is 1 for get or 2 for set and IsVariadic is false or undefined, the property cannot accept parameters; they are instead forwarded to the __Item property of the object returned by get.
Example,

Code: Select all

prop_setter(this, value [, params*])
Cheers.
User avatar
FredOoo
Posts: 186
Joined: 07 May 2019, 21:58
Location: Paris

Re: A strange __set() disturbance

10 Aug 2020, 01:09

Developping CF10 I got an error message about __Item.
Another strange thing is (but probably it's the same reason), in gsProp I shouldn't get key but Params with Params[1]=key.
(Alan Turing) « What would be the point of saying that A = B if it was really the same thing? »
(Albert Camus) « Misnaming things is to add to the misfortunes of the world. »
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: A strange __set() disturbance

10 Aug 2020, 02:05

Helgef wrote:
10 Aug 2020, 00:06
It is not a meta set being called. It is a prop setter.
and i never claimed it was. im highlighting the discrepancies between both functions' signatures(which apparently only serves to confuse people, see @vvhitevvizard's 41st gripe with v2[1, 2] and this case)
why isnt meta-set's(and others') Param variadic, again? i understand why the prop_setter's has to be this way(to allow for the "forwarding to get's retval's __Item" gimmick) but im struggling to come up with a good reason for why the metafunctions are that way(aside from "historical; havent gotten around to fixing it yet; we're replacing/deleting metafunctions altogether, so why bother with it now")
However, it doesn't work at all in CF8 with get: this.GetMethod ('gsProp2').bind (name)
So we can no longer recall a property by name. it's still a shame.
This is where normally you should set the example yourself ...
i trust u understand how what .Bind() does? u have bound the variable's value to the function's first not-yet-bound parameter. assuming u kept ur original signature gsProp( name, objThis, value:=unset ){, the value of name is bound to the first not-yet-bound parameter, which is a method's implicit this. when u go on to set the property, the parameter name receives the value of the target object, in other words: inside the setter, this contains the name and name contains the actual this(and objThis, the not-yet-bound "second parameter[,] is the value being assigned"; and any parameters thereafter contain the parameters that the setter was called with if it could be called successfully)
the solution? bind name to the second parameter(or any other position that u might end up defining it at): this.GetMethod('gsProp2').Bind(,name)
Exercise CF9 contains a heresy because in AHK a variable should never be undefined. It would be better to write this:

Code: Select all

class CF9 {
}
Then write directly in the properties. It works very well and that will probably be the conclusion of the topic.
unfortunately, i have no idea what u meant to say with this. nothing in AHK prevents u from declaring and (attempting) to use uninitialized variables
As for the strange order of the value / key parameters, I believe it shows that a full and complete use of __get / __ set with property name, parameters and internal get / set definition, are not yet fully developed .
No one has shown me otherwise yet. My conclusion is that it is better not to use them.
i dont know by what faulty logic uve managed to arrive at this non sequitur conclusion. u use them if ur requirements demand it. if u dont need ur object to handle random undefined methods being called on it and random undefined properties being accessed or set on it, dont use metafunctions.
User avatar
FredOoo
Posts: 186
Joined: 07 May 2019, 21:58
Location: Paris

Re: A strange __set() disturbance

10 Aug 2020, 02:45

Yes, with this.getMethod('gsProp').bind( , name ) and gsProp( name, value:=unset ){ CF8 is ok now.
I'm still working on CF10 but maybe I'll quite.

class CF9 {
}

Look at the print lines below. I can do everything I want.
But I cant do print param1, param2, param3 if param3:=unset

From the begining I had a code that works another way, writing in a iniFile section 'Versions' some key-values that are not knows in advance.
Translating from v2.0-a103 to v2.0-a119 I thought: let's try doing it with meta-methods… But they give more troubles than benefits.
There is not reason to redefine via this.defineProp( 'fileName', { value: o_NameNoExt '.ini' } ) when I can say this.fileName := o_NameNoExt '.ini'.
(Alan Turing) « What would be the point of saying that A = B if it was really the same thing? »
(Albert Camus) « Misnaming things is to add to the misfortunes of the world. »
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: A strange __set() disturbance

13 Aug 2020, 17:35

I can do everything I want. But I cant do print param1, param2, param3 if param3:=unset
if param3:=unset, test with IsSet() if it's set and provide a reasonable default if it isnt

if u want to make ur variadic print handle uninitialized variables, validate the parameters. eg if u know write() only works with Arrays and Strings, check if what ure passing to it is, in fact, an Array or a String
if u want to make ur variadic print detect uninitialized variables the caller may have passed in, it cant be done. parameters that collect into the variadic parameter are passed by value and an uninitialized variable's default value is an empty string.
metafunctions have specific purpose. if ure not going to take advantage of it, there's no point in using them(though there isnt anything stopping u either. an object's interface can be implemented with metafunctions alone)

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: malcev, Pyper, TheDewd and 54 guests