BoundFuncs Execute When Call Property Is Read

Report problems with documented functionality
[Shambles]
Posts: 100
Joined: 20 May 2014, 21:24

BoundFuncs Execute When Call Property Is Read

16 Dec 2018, 03:36

Demonstration Code

Code: Select all

Foo(X)
{
    MsgBox % "This should not execute."
}

Func("Foo").Bind("").Call
This problem occurs in version 1.1.30.01. It only occurs with BoundFuncs, not Funcs or user-defined function objects. It only occurs with the (non-existent) Call property, not other property names.

I had cause to write code like this. I have already found a workaround. It should still be fixed.
Last edited by [Shambles] on 04 Jan 2019, 15:01, edited 1 time in total.
safetycar
Posts: 435
Joined: 12 Aug 2017, 04:27

Re: BoundFuncs Execute When Call Property Is Read

31 Dec 2018, 13:17

This is annoying me too. I don't know how to Identify a Bound Function Object. I can't use IsFunc(Bound) and I can't use Bound.HasKey("Call") either. And like said above (Bound.Call) executes the function...
[Shambles]
Posts: 100
Joined: 20 May 2014, 21:24

Re: BoundFuncs Execute When Call Property Is Read

02 Jan 2019, 03:19

safetycar wrote:
31 Dec 2018, 13:17
This is annoying me too. I don't know how to Identify a Bound Function Object. I can't use IsFunc(Bound) and I can't use Bound.HasKey("Call") either. And like said above (Bound.Call) executes the function...
I discovered this problem while writing a library to do exactly what you are trying to do. It currently contains a workaround for this problem.

IsFuncObj(Value) from my library does what IsFunc(Value) should have done, tell you if something is a function. I had to name it something other than "IsFunc" to avoid clobbering the built-in function. The "Obj" suffix is a naming scheme I use to identify second-class objects, ones that do not support Object's interface (i.e. ones that are "incomplete"). If you want to know that something is a BoundFunc object specifically, Type(Value) from my library will tell you that. I hope it is helpful.

I do hope this will be fixed though. It cost me over an hour of debugging time.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: BoundFuncs Execute When Call Property Is Read

02 Jan 2019, 05:13

I fail to see how this is a bug - after all the documentation does not state that this doesn't happen - or what happens if you get the call element in a boundfunc.
I agree with you though that this is a good suggestion.
But I still don't see how it will help you identifying boundfuncs.
Recommends AHK Studio
[Shambles]
Posts: 100
Joined: 20 May 2014, 21:24

Re: BoundFuncs Execute When Call Property Is Read

02 Jan 2019, 17:16

nnnik wrote:
02 Jan 2019, 05:13
I fail to see how this is a bug - after all the documentation does not state that this doesn't happen - or what happens if you get the call element in a boundfunc.
I agree with you though that this is a good suggestion.
But I still don't see how it will help you identifying boundfuncs.
My justification for considering this a defect are:
  • it is undesirable
  • it is inconsistent with the behavior of every other part of the language (e.g. reading the Call property on a Func does not cause it to execute, reading the Call property on a user-defined type that does or does not have one does not cause anything to execute, reading the Call property on a file object does not cause nasal demons to pour forth or the printer to catch fire, etc., even though the manual does not guarantee my safety from such threats)
An exception being thrown when reading a non-existent property would be excusable, at least if it happened consistently in every similar situation, especially if there was some way to know if a property existed, or better yet, the reasonable expectation that similar things will have similar interfaces and thus if the type can be made to work with an operation it will work without special effort and if it cannot be made to work it will report an error, but this is not the world we live in, so programmers like me have gotten used to trying to do things in the hopes that they will work.

As for identifying BoundFuncs, being able to attempt to read the Call property without a function object executing is not directly related to that, but it is related to identifying functions in general.

My type checking library can recognize built-in types. The built-in types that are functions are Func and BoundFunc. There are also user-defined types that can act as functions. To recognize functions in general using this information, you can use a recursive algorithm. A function is either a Func, a BoundFunc, or a user-defined type with a Call property that is either a Func, BoundFunc, or a user-defined type with a Call property... The code I wrote worked this way. Unfortunately it occasionally caused bizarre behavior. I tracked this bizarre behavior down to BoundFuncs executing when their Call property is read.

I had already linked to the relevant code, which even has comments about the problem and how to work around it, but it appears nobody is looking at it. Hopefully this spells things out adequately.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: BoundFuncs Execute When Call Property Is Read

03 Jan 2019, 04:01

reading the Call property on a user-defined type that does or does not have one does not cause anything to execute
it executes get if implemented.

Looking at the (v2) implementation, I see that BoundFunc handles invoking call the same way regardless if it is set, get or call, so you can even do bf.call[x], bf.call := x or bf[x] := y, which will pass x,y as parameters to the function. Until BoundFuncs has any documented properties, I don't see any reason to handle set and get.
it is undesirable
At least it isn't desirable, as far as I am concerned.

Cheers.
[Shambles]
Posts: 100
Joined: 20 May 2014, 21:24

Re: BoundFuncs Execute When Call Property Is Read

03 Jan 2019, 07:14

Helgef wrote:
03 Jan 2019, 04:01
reading the Call property on a user-defined type that does or does not have one does not cause anything to execute
it executes get if implemented.

Looking at the (v2) implementation, I see that BoundFunc handles invoking call the same way regardless if it is set, get or call, so you can even do bf.call[x], bf.call := x or bf[x] := y, which will pass x,y as parameters to the function. Until BoundFuncs has any documented properties, I don't see any reason to handle set and get.
it is undesirable
At least it isn't desirable, as far as I am concerned.

Cheers.
I am quite certain that there is an explanation in both v1's and v2's implementation for this behavior. That does not mean the behavior as implemented is as it should be. Source code is not a holy text that must be unquestioningly obeyed and never changed.

It is undesirable:
  • This behavior is not necessary. If you want to call the function that is stored in the Call property, then you can use the syntax that unambiguously calls it.
  • This behavior prevents a desirable operation. If implemented consistently, it would prevent you from being able to 'tear off' a method, which is just a function. This is occasionally useful (e.g. when you have preexisting code that calls a supplied function instead of a method).
  • This behavior is dangerous. It requires the programmer to know whether a property contains a function or not without being able to read it to avoid executing code that might have destructive side effects.
  • This behavior is inconsistent with the rest of the language. If you declare this to be desirable behavior, then you must also declare Funcs and user-defined function objects to be defective.
And before you tell me that BoundFuncs do not really have methods implemented as functions with an implicit this, let me assure you that I am well aware and I understood your excuse based on the existing source code, and I am also well aware that built-in types should behave like user-defined types as much as possible so that programmers do not have to repeatedly write code to work around the unnecessary inconsistency. Actually writing that code is especially difficult, by the way, since v1 does not provide a standard way to recognize whether an object is a crippled built-in type or not. This whole problem was discovered while trying to write code to do that very thing.

Reading the property containing a function is not the same as executing said function. The programming language should not conflate these two inherently different acts. If it does so, it is wrong, for the same reason that displaying a message box should not delete a file. Hopefully v2 does not consistently make this mistake.

I would welcome reading a nonexistent property throwing an exception if it was implemented consistently and there was a way to determine if a property exists. Until that day, attempting to read a property that does not exist should evaluate to an empty string, like it does almost everywhere else (external COM objects being a notable exception, but that should probably not be blamed on AutoHotkey). And until that day, setting nonexistent or read-only properties should silently fail, like it does almost everywhere else (the same caveats apply).

This concept should be applied carefully, by the way. The current behavior of ObjGetBase(Object) could be excused by using it (you will eventually reach an object that has no base property), but that ignores that the purpose in calling ObjGetBase(Object) is to get 'the next level up' in the type hierarchy. Reaching the end of the type hierarchy should not be an error (i.e. it should return empty string, the closest thing AutoHotkey has to null). It should be expected behavior. The principle of least surprise should be the primary guiding light.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: BoundFuncs Execute When Call Property Is Read

03 Jan 2019, 08:34

I wouldnt say its inconsistent - there are a few other places where Get or Set can be used on Object Methods within AHKs build in Objects.
I'm sure that there is some documentation on this regarding compatability with vba or some other language.
Its a historical thing - so Im not convinced we can change it in v1.
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: BoundFuncs Execute When Call Property Is Read

03 Jan 2019, 09:56

I am quite certain that there is an explanation in both v1's and v2's implementation for this behavior. That does not mean the behavior as implemented is as it should be. Source code is not a holy text that must be unquestioningly obeyed and never changed.
[Shambles], obviously the source code is responsible for any behaviour, in no way did I try to justify the behaviour with it being caused by source code. I meant only to highlight the extent of the behaviour. I have suggested to change BoundFuncs to not handle getting and setting, for the alpha branch :arrow: #127. Anything else than calling Call on a BoundFunc would cause an exception.

Cheers.
[Shambles]
Posts: 100
Joined: 20 May 2014, 21:24

Re: BoundFuncs Execute When Call Property Is Read

03 Jan 2019, 10:15

Helgef wrote:
03 Jan 2019, 09:56
I am quite certain that there is an explanation in both v1's and v2's implementation for this behavior. That does not mean the behavior as implemented is as it should be. Source code is not a holy text that must be unquestioningly obeyed and never changed.
[Shambles], obviously the source code is responsible for any behaviour, in no way did I try to justify the behaviour with it being caused by source code. I meant only to highlight the extent of the behaviour. I have suggested to change BoundFuncs to not handle getting and setting, for the alpha branch :arrow: #127. Anything else than calling Call on a BoundFunc would cause an exception.

Cheers.
If that is for v2 (which I am told reports errors), then that is great (and as it should be)! If that is for v1, please reconsider.

In v1 we write code that expects invalid reads to return empty string and invalid writes to do nothing. Making this change in v1 will still require special-casing. This special-casing cannot normally be done (!!!) because there is no official way to recognize a BoundFunc. Putting programmers in bad situations without giving them the tools to cope is not right.

In v2 this is not a problem due to the existence of is and Type(Value).
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: BoundFuncs Execute When Call Property Is Read

03 Jan 2019, 10:22

It is for v2, which is being developed in the alpha branch.
[Shambles]
Posts: 100
Joined: 20 May 2014, 21:24

Re: BoundFuncs Execute When Call Property Is Read

03 Jan 2019, 10:34

nnnik wrote:
03 Jan 2019, 08:34
I wouldnt say its inconsistent - there are a few other places where Get or Set can be used on Object Methods within AHKs build in Objects.
I'm sure that there is some documentation on this regarding compatability with vba or some other language.
Its a historical thing - so Im not convinced we can change it in v1.
I am aware of no place, including in any other programming language, where reading a property causes its contents to execute. That is probably because it is obviously a foolish, dangerous idea.

I am aware of a great many places in AutoHotkey where this does not happen. Specifically, literally, every other situation I know of. If you tried it on an external COM object you would get an exception (probably with some inscrutable hexadecimal number that you would then have to Google to understand), but it still would not execute.

There is too much excuse making and not enough correction making.

You do not expect flames to shoot out of your refrigerator when you open its door. You do not expect this, not because it is physically impossible (though extremely unlikely without sabotage), but because it has not happened in the thousands of times before that you opened it and nobody has suggested to you that it could happen. Let us apply the common sense that we use in real life to programming, please. This is the lowest of bars.

Consistency, coherency, and safety are not the enemy.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: BoundFuncs Execute When Call Property Is Read

03 Jan 2019, 11:30

https://www.autohotkey.com/docs/objects ... tm#Example
https://www.autohotkey.com/docs/objects/File.htm#Seek
Are the cases I still remember. A while back I spend a lot of time trying to make call the only possible usage in this case.
At one point however I lost the overview and motivation.

This syntax is in use and we cannot change it for v1.
Recommends AHK Studio
[Shambles]
Posts: 100
Joined: 20 May 2014, 21:24

Re: BoundFuncs Execute When Call Property Is Read

03 Jan 2019, 11:57

nnnik wrote:
03 Jan 2019, 11:30
https://www.autohotkey.com/docs/objects ... tm#Example
https://www.autohotkey.com/docs/objects/File.htm#Seek
Are the cases I still remember. A while back I spend a lot of time trying to make call the only possible usage in this case.
At one point however I lost the overview and motivation.

This syntax is in use and we cannot change it for v1.
I see your links, but I am not sure how to observe this behavior myself. I do not want to perform dangerous operations on a file object, so tell me how to make an enumerator misbehave by reading properties. I have never encountered this problem myself. I am pretty familiar with enumerators, having written a complex one here. I assume the misbehavior I mentioned only occurs on built-in enumerators though.

If anyone was stupid enough to both notice this behavior and intentionally use it instead of the call syntax, I say they deserve to have their code broken. It is obviously not intended behavior, or if it is, it is intended by a sadist who hates their users.

If it is possible to make an enumerator or file object misbehave by reading properties, that is still not an adequate excuse to not fix it. Most properties do not cause their contents to execute when read. I just tried {}._NewEnum and it does not return an enumerator. This should be fixed in v1. Not fixing it could destroy data on your users' systems in plausible situations (e.g. they try to run an unpatched version of my type checking library, it tries to read Call on a BoundFunc, and causes code to run that overwrites or deletes files).
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: BoundFuncs Execute When Call Property Is Read

03 Jan 2019, 13:44

What I was refering to was specifically this piece of code in the documentation:

Code: Select all

enum := obj._NewEnum()
While enum[k, v]
Another example is the match Object:
https://www.autohotkey.com/docs/command ... atchObject
Brackets [] may be used in place of parentheses () if N is specified.

Code: Select all

RegExMatch("11", "O)^(.*)$", match)
Msgbox % match.pos[1]
Msgbox % match.len[1]
Msgbox % match.Value[1]
Im unable to remember the specific way to trigger related behavior in FileObjects.
It might be that Im mixing up Set and Get with Set, Get and Call.
And its not important enough for me to look into it really.

Breaking code that previously worked is not a thing that we intend to do - sometimes it cannot be avoided when people didn't use documented behavior.
However in this case (once again I dont know the specifics since I was only in the german forums at that time) it seems to be a feature which was once there for a reason.
However these things are practically in use and I want to remind you that you are not the only AHK user.
You are not even the only type of AHK user either - your ideals hardly matter when we progress this language for all of its users.
So we'd like to retain the current behavior where possible and only break it if something important has to change.

So when you one-sidedly decided that getting .call should do nothing, therefore relying on undocumented behavior you made the wrong assumption and ended up with broken code.
Now after this has happened you want the language to fit your needs and add new documented behavior that guarantees the things you expect, breaking everyone elses code in the process?
You are just being unreasonable imo.

Also isn't the problem you relying on undocumented behavior something you have to fix rather than the language?

I agree though - it's suprising and not intuitive - however it fits into the total chaos AHK v1 is.
AHK v2 will be a lot stricter with these checks and follow closer to the ideals you'd commonly expect from a programming language.

@Offtopic:
Since you are building a type thing you might be interested in this:
https://p.ahkscript.org/?p=d1147e77
Recommends AHK Studio
[Shambles]
Posts: 100
Joined: 20 May 2014, 21:24

Re: BoundFuncs Execute When Call Property Is Read

03 Jan 2019, 16:52

nnnik wrote:
03 Jan 2019, 13:44
What I was refering to was specifically this piece of code in the documentation:

Code: Select all

enum := obj._NewEnum()
While enum[k, v]
Another example is the match Object:
https://www.autohotkey.com/docs/command ... atchObject
Brackets [] may be used in place of parentheses () if N is specified.

Code: Select all

RegExMatch("11", "O)^(.*)$", match)
Msgbox % match.pos[1]
Msgbox % match.len[1]
Msgbox % match.Value[1]
Im unable to remember the specific way to trigger related behavior in FileObjects.
It might be that Im mixing up Set and Get with Set, Get and Call.
And its not important enough for me to look into it really.
Okay, fine, so a minority of built-in objects allow weird syntax. Limit the weird syntax to those situations. You already do this. As I have repeatedly pointed out, the normal behavior in v1 is for failed reads to return empty strings and failed writes to do nothing, except on external COM objects where they throw exceptions. Fixing BoundFunc objects to not be hazardous will not break anyone's code. There is no documentation suggesting people call BoundFuncs (and only BoundFuncs, not Funcs or user-defined function objects) by reading their Call property.
nnnik wrote:
03 Jan 2019, 13:44
Breaking code that previously worked is not a thing that we intend to do - sometimes it cannot be avoided when people didn't use documented behavior.
Do I ever wish that were true! If it was true, the addition of BoundFunc objects a year or two ago would not have destroyed two of my libraries by having an interface inconsistent with Func objects.

But sure, we can pretend that we care about code breaking. I am not suggesting you break the bad interface to the *.Enumerator, File, or RegExMatch objects. How about we just fix it everywhere reading-properties-calls-a-method is not documented as working? Doing so is obviously possible because most built-in types do not exhibit this bad behavior.
nnnik wrote:
03 Jan 2019, 13:44
However in this case (once again I dont know the specifics since I was only in the german forums at that time) it seems to be a feature which was once there for a reason.
A bad reason, I am sure. Most cases where AutoHotkey deviates from normal programming language design are very, very bad.

One example is the use of % (note: non-directional, unlike [], {}, and <>) brackets for substitution. For extra pain and suffering, this is required at random locations, so the programmer lives in the manual, constantly looking up where it is required and where it must not be done. Then doubling down on the mistake by introducing command substitution in v2, dooming AutoHotkey to bad performance (it will require constant reparsing) and encouraging inscrutable code.

1-based array indexing. And yes, I know the excuse is it is easy for novices (Is all this danger and inconsistency also easy for novices?). The problem is array indexing is not counting. Its the distance from the beginning of the array, and the distance from the beginning to the beginning is necessarily 0. That is why it is bad design to use anything other than 0-based array indexes. When you actually must use indexing, because you need to calculate the location (e.g. using an array like a circular buffer using modulo), you end up doing lots of error-prone - 1 and + 1 adjustments. Novices get over the confusion between counting (used when discussing array length) and array indexing pretty quickly. Experienced programmers have to deal with 1-based indexing forever!

Arrays with missing elements... This is a problem that could theoretically occur in Lua, which also made the mistake of conflating arrays and dictionaries (along with JavaScript and PHP), only the Lua standard library documentation warns you that everything will break if you have missing elements in your arrays. In AutoHotkey you actually have to use them if you need to call a function with optional arguments.

There is a mysterious (this conversation is evidence) hostility toward anything that might make life more comfortable or safer for the programmer. No error reporting in v1. Random interfaces. No way to identify the type in v1 so that you can figure out which interface to use.

I could go on for hours, and I did at one point.

I recall a famous blog post (that I cannot seem to find now) claiming that you do not know a programming language unless you can say 3 nice things about it, even if you hate it, so as evidence that I know AutoHotkey (other than having released several libraries, at least one of which is rather large), here goes...

Good Things About AutoHotkey
  • It has incredibly useful I/O facilities. If you need to automate any software installation, updating, (re)configuration, or uninstallation, AutoHotkey is the best tool available (at least that I know of).
  • It is easy to convert an AutoHotkey script and some installers into a self-installing executable. If you are a Windows sysadmin, this is extremely useful.
  • It is easier to call into AutoHotkey than almost any other programming language. Here I mostly refer to the "hotkey" feature from the name, but there is also a DLL version that appears to be pretty usable.
  • The ability to specify the stack frame an exception should refer to is unique and very useful for writing shared error reporting procedures. I have never seen it elsewhere and I use it heavily.
  • Methods just being functions that have an implicit this parameter is conceptually elegant and occasionally useful (I mentioned 'tearing off' methods before).
Hey, that's more than 3! I admit I would be hard pressed to come up with more, however. I do truly hate most of AutoHotkey's programming language.

I am not just trolling you. Trolls do not put this much effort into writing libraries.

I am a cranky user who complains a lot because I feel trapped having to use AutoHotkey because everything else is worse, but the bad programming language design keeps causing me problems. It is the programmer version of being in an abusive relationship.

I want things to get better. AutoHotkey, you need to go to counseling! You need to learn to learn from other programming languages instead of always trying to do everything differently even when it is worse than what everyone else is doing (e.g. your random syntax and random interfaces) or engaging in bad behavior that was last normalized decades ago (e.g. your Bash-like command substitution, massive overuse of mutable state (look at the reams of built-in variables!), and unstructured control flow (at least you do not force it on us any more)).

I am not sure if you are trolling me however. I need to get streams working for Facade and you seem to be being completely unreasonable about fixing an obvious defect in the behavior of BoundFunc objects. Nobody is depending on reading Call causing BoundFuncs to execute. Fix it, or at least stop making excuses for it so other people will fix it! AutoHotkey does not need your white knighting. Software does not improve by people enshrining destructive defects as features that must be supported forevermore. My patience is wearing thin.

Yes, I know you all do this in your free time and do not owe me anything. On the other hand, v2 is destined to destroy all existing AutoHotkey code. That makes me care very much about the transition being worthwhile. If you are going to break all of my code, that is worth it to me if and only if you solve the many serious problems with AutoHotkey's design. Please keep in mind that I am trying to give back to the community in the form of libraries.
nnnik wrote:
03 Jan 2019, 13:44
However these things are practically in use and I want to remind you that you are not the only AHK user.
You are not even the only type of AHK user either - your ideals hardly matter when we progress this language for all of its users.
Thank you! I had forgotten that the universe does not revolve around me!

Now I will help you see reality. Most of your users that think AutoHotkey is well designed do not know any other programming language besides AutoHotkey and are therefore in no position to make claims about how easy it is to learn or use. Many of them no doubt found it extremely difficult to learn. The lack of error reporting and consistency will take quite the toll on the novice programmer. A certain amount of Stockholm Syndrome is to be expected. Novice programmers are unlikely to write code of enough complexity to notice some problems (like the one in this thread). It is not rare for those from outside the chorus of praise to complain on these forums, and I frequently see the kind of white knighting you are engaging in right now occurring and even attempts to tell these people that they are wrong in some sort of factual way, even (if not especially) when they are not. This needs to stop! I do not like having to converse as if I am trying to brow-beat someone into submission constantly, but this sort of behavior makes it necessary!
nnnik wrote:
03 Jan 2019, 13:44
So we'd like to retain the current behavior where possible and only break it if something important has to change.
Yes, something important like fixing defects that could, in plausible situations, cause data loss.
nnnik wrote:
03 Jan 2019, 13:44
So when you one-sidedly decided that getting .call should do nothing, therefore relying on undocumented behavior you made the wrong assumption and ended up with broken code.

Now after this has happened you want the language to fit your needs and add new documented behavior that guarantees the things you expect, breaking everyone elses code in the process?
I do not believe anyone is relying on reading Call on (only) BoundFuncs causing them to execute. I demand uncontrived, unmanufactured evidence to the contrary to believe that fixing this defect will break anyone's code.
nnnik wrote:
03 Jan 2019, 13:44
You are just being unreasonable imo.
You are the one insisting on preserving a dangerous defect. I am the one who found it, reported it, explained how to trigger it reliably, explained why the code that triggers it was useful, and specified how it should be fixed. I am not the one being unreasonable here.

I am the person who comes to the doctor with an infection and asks for medication to kill it. You are the doctor telling me that the disease has a right to live.
nnnik wrote:
03 Jan 2019, 13:44
Also isn't the problem you relying on undocumented behavior something you have to fix rather than the language?
Ah, I am so glad you asked!

See, AutoHotkey v1 has this horrible design flaw, some of which seems to live on in v2. Values do not have a consistent interface. For example, Funcs have a Bind(Args*) method and a slew of useful properties, but BoundFuncs do not. You also cannot easily tell when an attempt to use one interface fails (so, for example, you could try something else). That is because no mechanism is provided for detecting types (e.g. answering "Is this a file object?") or interfaces (e.g. answering "Does this have a Bind(Args*) method?") and most errors are not reported.

If you think about that combination of facts carefully, you will realize that a (artificial) problem was created that is not solvable within the system.

So how does one cope with this? Why, by doing the only thing you can do, relying on undocumented behavior! There are ways involving examining memory addresses to identify the type of a built-in. There are ways of navigating the object graph to identify the type of user-defined objects (this part is documented). With some cleverness (e.g. that recursive algorithm for identifying both built-in and user-defined function objects), you can figure out how to dispatch to code that is known to work.

Since I am not certain you could be bothered to read the code I linked, the reason reading the Call property of an unknown type was a reasonable and useful thing to do is, without it, I would have had to duplicate part of the body of the loop that simulates tail recursion. On the first pass, you want to test if what the user passed is a Func or BoundFunc. If it is not one, you want to try to get the Call property's value to prepare for the next pass. If the value is a user-defined function object the Call property's contents will probably be a Func or BoundFunc. It could be another user-defined type, however. If no Call property exists, you would expect to get an empty string for the 'next thing to test if it is a Func or BoundFunc'. This is the termination condition for the recursion/loop.

Now you are in the position of someone that locked me in a room, forcing me to break down the door so that I do not die of thirst, and then you complain about your destroyed door! If you do not want me to use undocumented behavior, DO NOT MAKE IT NECESSARY!!!

Well-designed dynamically type checked programming languages simply store the type information along with the value. They either provide a standard procedure to identify the type of a value (simply reading this information, instead of playing detective like I have had to) so that the programmer can dispatch to code that will handle it correctly (e.g. most Lisp-like languages) or they use a standard interface for every common behavior (e.g. Smalltalk). Most do both out of good taste. Inconsistency is of no help to anyone, so standard interfaces are the norm. Type detection procedures are more commonly used in functional languages for dispatching and polymorphism via standard interfaces is more commonly used in object-oriented languages, but even object-oriented languages occasionally use type detection procedures for things like producing helpful error messages.

This problem is not difficult to figure out how to solve. Just pay attention to what other programming languages have done and how that worked out.
nnnik wrote:
03 Jan 2019, 13:44
I agree though - it's suprising and not intuitive - however it fits into the total chaos AHK v1 is.
Not only is it surprising and not intuitive, it is downright wrong!

Total chaos is not desirable.
nnnik wrote:
03 Jan 2019, 13:44
AHK v2 will be a lot stricter with these checks and follow closer to the ideals you'd commonly expect from a programming language.
I am sure that will be of great help, just as soon as it becomes the primary version. Not that I want it to be rushed. v2 does not go nearly far enough fixing AutoHotkey's problems. Maybe it will in 10 more years. Until then, people like me will have to use undocumented behavior to cope in v1, unless an alternative is provided.
nnnik wrote:
03 Jan 2019, 13:44
@Offtopic:
Since you are building a type thing you might be interested in this:
https://p.ahkscript.org/?p=d1147e77
I already built a type thing. It works, despite this defect. This defect cost me over an hour trying to figure out why some test code was behaving as it was.

Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 40 guests