Functions returning unset by default (and divergent topics)

Discuss the future of the AutoHotkey language
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Functions returning unset by default (and divergent topics)

Post by lexikos » 21 Nov 2022, 03:13

[Topic split from Arrays mistaken as strings?]
sirksel wrote:
17 Nov 2022, 00:57
It's actually a really common error. Whenever you see that String doesn't have a property you're looking for (when you're expecting some other type), just remember it's often because that String is the empty ("") string.

Even apart from just an error like the one in your example... since the empty string is falsey, it's often used instead of Error to signal that a function fails. Whenever I see that "String has no property named..." message, I quickly MsgBox the variable without the property to see if, in fact, it is an empty string. Then I know better what to debug... I have an empty return problem, not a property problem.

I think it would be better if functions had no return value by default, and any attempt to use the non-existent return value raised an error - just like if you try to read a variable which has no value (or invoke a method or property on the variable). Defaulting to "" would be even worse if strings had properties such as str.Length and char := str[index] by default, as it would appear that you just have an empty array. Unfortunately I didn't seriously consider it until late in beta - far too late to be changing the documented and well-known default return value of functions. I'm thinking that v2.1 and future will allow scripts to opt in to such backward-incompatible changes.

OpalMonkey
Posts: 18
Joined: 23 Jan 2014, 03:02

Re: Arrays mistaken as strings?

Post by OpalMonkey » 21 Nov 2022, 05:09

lexikos wrote:
21 Nov 2022, 03:13
I think it would be better if functions had no return value by default, and any attempt to use the non-existent return value raised an error - just like if you try to read a variable which has no value (or invoke a method or property on the variable).
I, for one, would absolutely love that. If the ability to use unset as a return value was added, would it be possible for the two to coexist, so long as Return unset was explicitly defined, or would they do the same thing?
lexikos wrote:
21 Nov 2022, 03:13
Defaulting to "" would be even worse if strings had properties such as str.Length and char := str[index] by default, as it would appear that you just have an empty array.
Is this something you are considering for a future (v2.1 or even v3.0) release? It seems like a nice extension to a lot of the v2.0 changes.
lexikos wrote:
21 Nov 2022, 03:13
I'm thinking that v2.1 and future will allow scripts to opt in to such backward-incompatible changes.
I'm practically salivating at the thought. The breaking changes in v2.0 have made it much nicer to work with and way more fun. I eagerly await the day when more of those come around. Though, I'm sure it'll be a while since v2.0 isn't even quite out the door yet.

User avatar
RaptorX
Posts: 371
Joined: 06 Dec 2014, 14:27
Contact:

Re: Arrays mistaken as strings?

Post by RaptorX » 21 Nov 2022, 09:04

lexikos wrote:
21 Nov 2022, 03:13
I think it would be better if functions had no return value by default, and any attempt to use the non-existent return value raised an error - just like if you try to read a variable which has no value (or invoke a method or property on the variable). Defaulting to "" would be even worse if strings had properties such as str.Length and char := str[index] by default, as it would appear that you just have an empty array. Unfortunately I didn't seriously consider it until late in beta - far too late to be changing the documented and well-known default return value of functions. I'm thinking that v2.1 and future will allow scripts to opt in to such backward-incompatible changes.
I completely agree that functions that dont have an explicit return value should raise an error if you try to access a value from it.
OpalMonkey wrote: I'm practically salivating at the thought. The breaking changes in v2.0 have made it much nicer to work with and way more fun. I eagerly await the day when more of those come around. Though, I'm sure it'll be a while since v2.0 isn't even quite out the door yet.
I think exactly the same! I think v2 is a great step forward and hope we remove as many quirks from v1 :)
Projects:
AHK-ToolKit

lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Arrays mistaken as strings?

Post by lexikos » 21 Nov 2022, 17:09

OpalMonkey wrote:
21 Nov 2022, 05:09
If the ability to use unset as a return value was added, would it be possible for the two to coexist, so long as Return unset was explicitly defined, or would they do the same thing?
The two whats? Explicit and implicit return unset? They would be equivalent.
Is this something you are considering for a future (v2.1 or even v3.0) release?
No. I don't feel the need for such abstraction over strings. Much more interesting things fill my plans.
Though, I'm sure it'll be a while since v2.0 isn't even quite out the door yet.
v2.0 is basically in bug-fix-only mode, so if I want to do anything interesting, it will be in an experimental branch or v2.1-alpha branch.

RaptorX wrote:
21 Nov 2022, 09:04
I think v2 is a great step forward and hope we remove as many quirks from v1 :)
What does that mean? Quirks were removed from v1, and the result was v2. In retrospect, a different strategy might have made transitioning to v2 easier, but I am not going to revisit over 10 years worth of changes. I will not be devoting much time to the v1 branch.

User avatar
RaptorX
Posts: 371
Joined: 06 Dec 2014, 14:27
Contact:

Re: Arrays mistaken as strings?

Post by RaptorX » 21 Nov 2022, 22:09

lexikos wrote:
21 Nov 2022, 17:09
What does that mean? Quirks were removed from v1, and the result was v2. In retrospect, a different strategy might have made transitioning to v2 easier, but I am not going to revisit over 10 years worth of changes. I will not be devoting much time to the v1 branch.
oh no, I did not imply to port anything to v1 at all! haha
I meant removing lingering oddities in v2 that are quirks from v1.

For example SplitPath and some other functions still force you to use syntax that feels like remnants of v1. I would have love them returning an object as FileSelect and such.

After using v2 im not going back my friend, you have done an amazing job and I am extremely grateful for it :D
Projects:
AHK-ToolKit

lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Arrays mistaken as strings?

Post by lexikos » 21 Nov 2022, 22:35

Output and by-reference parameters are not a quirk of v1. They are an extremely common concept. They do not even work the same in v1 and v2.

"As many" would imply the same amount again. There aren't nearly that many quirks left.

sirksel
Posts: 222
Joined: 12 Nov 2013, 23:48

Re: Arrays mistaken as strings?

Post by sirksel » 21 Nov 2022, 22:52

@lexikos, any chance you could share a sneak peek high-level of the "more interesting things" for 2.1? I can't wait to hear.

As for unset... I know that unset isn't currently falsey, for reasons you've previously enumerated. Any chance that would change in 2.1?

Assuming not, is there a chance you would consider one or two new operators, especially if unset is a possible return value from a function?

1. ?. such that obj?.prop1[x]?.prop2(y1, y2)?.prop3? would return unset if anything in the chain returned unset or if any of those properties did not exist. Then one could write obj?.prop1[x]?.prop2(y1, y2)?.prop3? ?? default, without all the separate tests and HasProps. Maybe it's less of a new operator and more of an extension of the current obj? "maybe" notation.

2. Perhaps some shortcut equality operator ?==, such that retval ?== compval is equivalent to IsSet(retval) ? retval == compval : unset and would preserve the short circuit. Hard to offload this to even a one-liner function today because you lose the short circuit.

Actually, it might instead just be an extension of the current "maybe" notation, such that retval? == compval? just returns unset if either are unset. And retval? == compval would return unset if retval were unset but throw if compval were unset (because it doesn't have the question mark).

I guess it could possibly even be more general... perhaps terminating a variable or expression with ? allows the unset to pass through any operator (but not any function where a non-optional parameter is required in that place), causing the operator's result to be unset. For complicated expressions, the terminal question mark on a subexpression would be the coder's acknowledgement that "yeah, I know this might be unset, but I'll test the final result later". Then it either gets explicitly tested (or ??ed or Errored out) at the end, once the ? is no longer present or once a function or control-flow statement is requiring a non-optional value.

On second thought, maybe this more general approach is an implementation nightmare? Or maybe you don't like propagating unsets at all, lest it becomes like the NPE nightmare that was/is Java? Anyhow, just a thought.

OpalMonkey
Posts: 18
Joined: 23 Jan 2014, 03:02

Re: Arrays mistaken as strings?

Post by OpalMonkey » 22 Nov 2022, 06:41

lexikos wrote:
21 Nov 2022, 17:09
The two whats? Explicit and implicit return unset? They would be equivalent.
I suspected that would be the case. The wording of "if functions had no return value by default" just made me wonder if it would be defaulting to unset or if this would be handled in some other way. Thanks for confirming.
No. I don't feel the need for such abstraction over strings.
Good to know. I was mostly just curious in case I decide to mess around with adding on to primitives, only for it to end up as wasted time. Though, now that I look at the documentation again and do a little testing, it's pretty quick and straightforward. Guess I know what I'm doing soon.
[…] Much more interesting things fill my plans.

v2.0 is basically in bug-fix-only mode, so if I want to do anything interesting, it will be in an experimental branch or v2.1-alpha branch.
Glad there are interesting plans. Guess I was more just trying not to sound like I expect anything to happen at a specific pace.

RaptorX wrote:
21 Nov 2022, 22:09
After using v2 im not going back my friend, you have done an amazing job and I am extremely grateful for it :D
Seconded! It's unlikely any of my v1 code will ever get anything more than minor maintenance from now on.

sirksel wrote:
21 Nov 2022, 22:52
Maybe it's less of a new operator and more of an extension of the current obj? "maybe" notation.
I keep finding myself trying to write If param? rather than If IsSet(param), so it would certainly feel natural to have some extensions to the ? operator. Not going to pretend I have any real insight on what would make sense, though.

User avatar
RaptorX
Posts: 371
Joined: 06 Dec 2014, 14:27
Contact:

Re: Arrays mistaken as strings?

Post by RaptorX » 22 Nov 2022, 16:18

lexikos wrote:
21 Nov 2022, 22:35
Output and by-reference parameters are not a quirk of v1. They are an extremely common concept. They do not even work the same in v1 and v2.
I know that output parameters in general are a common concept (a very annoying one at that) but I was referring to the fact that you decided to use arrays/objects as a return value for many commands but kept some of them with their parameter counterpart.

compare:

Code: Select all

SplitPath(fullPath,,,,, &Drive) ; you have to know how many commas to put just to get the drive
msgbox Drive

; to

files := FileSelect("M")
msgbox files[1]

; or any of the other guys that return objects
main := GUI()
menu := Menu()
hook := InputHook()
file := File()

; This would make much more sense to me and be more consistent with the direction v2 is taking in my opinion
path := SpitPath(fullPath)
msgbox path.drive


lexikos wrote:
21 Nov 2022, 22:35
"As many" would imply the same amount again. There aren't nearly that many quirks left.
I totally agree, there aren't many quirks left and that's exactly the reason I switched to v2 in a heartbeat and not looking back.
Is just that I feel that I switched to v2 to avoid certain syntax that is still present in a few commands.

I just think that you moved in to favor objects/arrays in many commands, even revamping the whole GUI/Menu concepts to work as objects.
So it looks like you are going in that particular direction. Having many commands still using output variables just make a few things inconsistent.

Those inconsistencies are moot with Intellisense and autocomplete, but sometimes I find myself developing in remote machines or outside of my normal development environment. Trying to remember which parameter is the one that returns what I need is really annoying and I keep having to open the help file just to find out which parameter I needed.

To reiterate, I think you have done an amazing job. I'm just patiently waiting for v2 to completely ditch certain things. It's always nice to shoot for better...
Last edited by RaptorX on 22 Nov 2022, 17:05, edited 2 times in total.
Projects:
AHK-ToolKit

lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Arrays mistaken as strings?

Post by lexikos » 22 Nov 2022, 16:56

RaptorX wrote:
22 Nov 2022, 16:18
compare:
Apples and oranges. FileSelect returns a variable number of values, all with the same meaning.
I just think that you moved in to favor objects/arrays in many commands, even revamping the whole GUI/Menu concepts to work as objects.
Firstly, I did not revamp the Gui concept; fincs did. Secondly, it is not using objects for the sake of using objects. Each paradigm has its uses. Gui is much more complex than a single function returning a few values. A script often works with multiple Gui windows or menus, but v1 does this via globally named "objects". For a single function returning multiple values, it is basically only a minor difference of convenience (subjectively favouring one or the other method) and performance (output parameters are faster to initialize and access, and permit the function to skip calculating values that aren't needed). The argument for easier memorization isn't specific to output parameters, but to any function with a large number of (especially optional) parameters; and there are other solutions, like named parameters.

Even the Gui objects use output parameters.
Having many commands still using output variables just make a few things inconsistent.
Can you explain how the inconsistency is detrimental or even relevant in this case?

User avatar
RaptorX
Posts: 371
Joined: 06 Dec 2014, 14:27
Contact:

Re: Arrays mistaken as strings?

Post by RaptorX » 22 Nov 2022, 17:54

I have noticed that you usually take information always through the lens of either efficiency or practicality and most of the time after you explain what thought process went into a decision you made I agree with you on the basis of correctness. But sometimes correctness makes a few things a bit more difficult to the untrained person.

I usually bring topics from a totally different perspective, Im an educator mainly, so take everything I say with a grain of salt.
Just try to remember that my input is just to try and bring a different point of view.
lexikos wrote:
22 Nov 2022, 16:56
Apples and oranges. FileSelect returns a variable number of values, all with the same meaning.
I am aware. I used the example to try to illustrate the visual difference between the two commands.

Notice how simple stuff can confuse people.
Some changes might be only aesthetical but some times that improves the experience more than you can imagine.
lexikos wrote:
22 Nov 2022, 16:56
Firstly, I did not revamp the Gui concept; fincs did.
Oh I didnt know this little detail :)
lexikos wrote:
22 Nov 2022, 16:56
For a single function returning multiple values, it is basically only a minor difference of convenience (subjectively favouring one or the other method) and performance (output parameters are faster to initialize and access, and permit the function to skip calculating values that aren't needed).
Totally agree, I am talking about a very admittedly subjective point of view but I argue that has some basis on ease of use for the end developer.

The performance point you are mentioning is exactly what I suspected was the reason those functions were designed that way.
lexikos wrote:
22 Nov 2022, 16:56
The argument for easier memorization isn't specific to output parameters, but to any function with a large number of (especially optional) parameters; and there are other solutions, like named parameters.
Yes, this is basically a very interesting point.

I would be in favor of splitting certain functions into different functions as done with the Win functions.
GetPathDir(path) or GetPathFileName(Path) make much more sense than 5 commas in a row.

I was dealing with a com object recently and saw that It had no less than 18 parameters...
expression.OpenText (FileName, Origin, StartRow, DataType, TextQualifier, ConsecutiveDelimiter, Tab, Semicolon, Comma, Space, Other, OtherChar, FieldInfo, TextVisualLayout, DecimalSeparator, ThousandsSeparator, TrailingMinusNumbers, Local) most of them optional, good luck knowing how many commas you need before setting the DecimalSeparator option :D

I do get that this design is because options were built over time but it makes it extremely difficult to a newbie to remember what to do when you have hundreds of other functions just like that. Intellisense helps, but you dont always have your tools at your disposal, you should know what to do without relying on intellisense xD
lexikos wrote:
22 Nov 2022, 16:56
Even the Gui objects use output parameters.
Which is basically one of the things I'm complaining about... the GUI is an object, but then some of its methods dont return objects? why?! (I can definitely hear you whispering: performance...) :lol:
lexikos wrote:
22 Nov 2022, 16:56
Can you explain how the inconsistency is detrimental or even relevant in this case?
Again, if you only see stuff though the performance lens, yeah... is not relevant or detrimental.

But if you switch perspective for a second:
Whoever is using AHK must remember which commands return objects/arrays and which need parameters. When you are trying to teach a concept, you have to battle not only with the concept but the differences in paradigm in different commands, which makes learning a bit more complex than need be.

You know those functions by heart and inside out. But we, mere mortals, are usually battling with those kind of little details most often than we would like to.

This is a totally subjective thing, of course, so I will be unable to convince you that this is at all important.
Specially since I noticed your interest in named parameters which would definitely solve this issue.
Projects:
AHK-ToolKit

lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Functions returning unset by default (and divergent topics)

Post by lexikos » 23 Nov 2022, 04:03

I think discussions have diverged far and wide from the original topic of forgetting return, so I have split the topic.

sirksel wrote:
21 Nov 2022, 22:52
As for unset... I know that unset isn't currently falsey, for reasons you've previously enumerated. Any chance that would change in 2.1?
No. Have any of the reasons been invalidated?

It is intended to be as close to being the absence of a value as possible, rather than being a value representing the absence of a value, which ends up being ambiguous. Expressions which permit yielding no value must be explicitly marked, making them clearly identifiable, and making it less likely to fall into the trap of an unexpected "null" value being misinterpreted.

If you expect a variable to potentially have no value, you must provide the default value at the point you reference the variable. If you want unset to be treated as false, you just write var ?? false.
1. ?. such that obj?.prop1[x]?.prop2(y1, y2)?.prop3? would return unset if anything in the chain returned unset or if any of those properties did not exist.
In JavaScript this is known as the optional chaining operator. I do not see what it has to do with your other comments, but it is planned.
2. Perhaps some shortcut equality operator ?==, such that retval ?== compval is equivalent to IsSet(retval) ? retval == compval : unset and would preserve the short circuit.
One problem is that we have several equality operators already, let alone other comparison operators.

What if both operands can be unset?
Actually, it might instead just be an extension of the current "maybe" notation, ...
This is more sensible.

Perhaps retval? == compval is sufficient to indicate that the operation should short-circuit if the value of retval is missing, but I am not sure that I would remember while writing code that compval mightn't be evaluated. Normally the operands are evaluated left to right, so (b() == a?) would either have to alter the order of evaluation or be incapable of short-circuit, inconsistent with (a? == b()). It's easier to require the use of ternary.

any chance you could share a sneak peek high-level of the "more interesting things" for 2.1?
I will start another topic.

lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: SplitPath returning an object

Post by lexikos » 23 Nov 2022, 05:40

RaptorX wrote:
22 Nov 2022, 17:54
I am aware. I used the example to try to illustrate the visual difference between the two commands.
The visual difference is the least important aspect. They are clearly from two different categories of functions, and have output of completely different nature. It could be said that visual distinction between functions of differing nature is more helpful than having them appear the same but act differently.
Notice how simple stuff can confuse people.
Some changes might be only aesthetical but some times that improves the experience more than you can imagine.
...
When you are trying to teach a concept, you have to battle not only with the concept but the differences in paradigm in different commands, which makes learning a bit more complex than need be.
I don't find these generalisations to be compelling or particularly relevant to the topic of SplitPath.
The performance point you are mentioning is exactly what I suspected was the reason those functions were designed that way.
SplitPath was designed long before there were objects. SplitPath v2 is the way it is because I did not believe it would be better to return an object instead, considering multiple factors and ultimately being decided by my opinion.
Which is basically one of the things I'm complaining about... the GUI is an object, but then some of its methods dont return objects? why?!
Your question implies that every method should return an object, which is irrational. Methods and functions return whatever is appropriate to represent their output, not to reflect the form of the method or function itself. Also, functions are objects.
Again, if you only see stuff though the performance lens, yeah... is not relevant or detrimental.
It is not a matter of perspective (or anything to do with performance), but of reasoning and logic.
Whoever is using AHK must remember which commands return objects/arrays and which need parameters.
Whoever is using a function must remember (or be able to determine by using tools or documentation) what the function's parameters are and what it returns, regardless of whether they are objects. They must remember that FileSelect returns a filename or an array of filenames, while SplitPath hypothetically would return an object with properties that have specific names. They would need to also memorise the property names, which might be easier than memorising the parameter order. If the editor provides hints for the parameters but not the properties (as it can't infer that the object you are accessing has the properties SplitPath gave it), any advantage properties have for memorisation may be lost.

If SplitPath returning an object helps memorisation, it will have nothing to do with the fact that other functions also return objects. Each object is different, and there's not much similarity in the meaning of an array vs. what SplitPath would return, or how they would be used.

User avatar
RaptorX
Posts: 371
Joined: 06 Dec 2014, 14:27
Contact:

Re: SplitPath returning an object

Post by RaptorX » 23 Nov 2022, 09:33

lexikos wrote:
23 Nov 2022, 05:40
The visual difference is the least important aspect. They are clearly from two different categories of functions, and have output of completely different nature. It could be said that visual distinction between functions of differing nature is more helpful than having them appear the same but act differently.
Thats where our opinions differ.
It might not be important when looking at it from the technical point of view, but it might be really important when taking into account ease of learning and ease of use. It might even allow the developer to be more efficient by removing the time we take checking the documentation for the 101th time to verify which parameter is the one I wanted to access.
lexikos wrote:
23 Nov 2022, 05:40
Your question implies that every method should return an object, which is irrational. Methods and functions return whatever is appropriate to represent their output, not to reflect the form of the method or function itself. Also, functions are objects.
Let me clarify that. I do not think every method should return an object.
If the method just returns 1 value (a string, a number) then it should just return 1 value. If the method returns a collection of values then returning an array might be the best approach.

If the method returns a bunch of different properties of the item you passed to it, then an object or a map might be a good approach.
lexikos wrote:
23 Nov 2022, 05:40
It is not a matter of perspective (or anything to do with performance), but of reasoning and logic.
Depends on how you use logic. In this case you are choosing to place lower value to user experience and for that reason you reach that particular conslusion.

By using the same logic/reasoning but applying different values to other options you might reach a different conclusion. It doesnt mean that you are not using reasoning/logic, it just means you value things differently.

You dont care much about the visual appeal of not having to write many commas to get a value. And that is alright.

Other people do care about such things. And when you are developing something that appeals to a mass of people then your logic should take into account the value other people place on stuff you dont really care about.
lexikos wrote:
23 Nov 2022, 05:40
Whoever is using a function must remember (or be able to determine by using tools or documentation) what the function's parameters are and what it returns, regardless of whether they are objects. They must remember that FileSelect returns a filename or an array of filenames, while SplitPath hypothetically would return an object with properties that have specific names. They would need to also memorise the property names, which might be easier than memorising the parameter order.
We are hardwired to learn names, so I would definitely argue that it is far easier to learn names specially if they are intuitive.
If I want the file name of a path, then Path.FileName would be just the thing Im looking for, as opposed to SplitPath Path ,,,, &OutNameNoExt
lexikos wrote:
23 Nov 2022, 05:40
If the editor provides hints for the parameters but not the properties (as it can't infer that the object you are accessing has the properties SplitPath gave it), any advantage properties have for memorisation may be lost.
As IDEs provide hints, its trivial to have the properties listed in the short description of the method/function and that wouldnt be a problem.
And I would argue I wouldn't need much time to remember whether I need Path.FileName or Path.FileNameExt.

I will have much more trouble remembering that the 1st parameter after the input var is the &OutFileName and the 4th parameter is the same thing but without the extension. You must not only remember the position but the irrationality of them being that far apart (I would have expected having FileName and FileNameNoExt being next to each other) makes it harder than it should be.
lexikos wrote:
23 Nov 2022, 05:40
If SplitPath returning an object helps memorisation, it will have nothing to do with the fact that other functions also return objects. Each object is different, and there's not much similarity in the meaning of an array vs. what SplitPath would return, or how they would be used.
Completely agree with this statement. I was mentioning the other functions in the context of visual consistency which I argue helps with ease of use and probably even makes coding more efficient in certain conditions as you dont have to be opening the documentation, over and over for the same thing.
Projects:
AHK-ToolKit

lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: SplitPath returning an object

Post by lexikos » 23 Nov 2022, 20:15

RaptorX wrote:
23 Nov 2022, 09:33
It might even allow the developer to be more efficient by removing the time we take checking the documentation for the 101th time to verify which parameter is the one I wanted to access.
This has nothing to do with the visual difference between FileSelect and SplitPath.
You dont care much about the visual appeal of not having to write many commas to get a value.
This line of the discussion wasn't about the pros or cons of returning an object or using output parameters. It was about the purported inconsistency between FileSelect and SplitPath. I maintain that these are different categories of functions, and having them appear visually similar while still behaving differently is not beneficial in any meaningful way.
Other people do care about such things.
People sometimes hold opinions that they can't rationally explain or justify. Anyone is free to care about whatever they want, while that on its own will mean nothing to me, because I'm also free to care or not care about whatever I want.
And when you are developing something that appeals to a mass of people ...
Appealing to a mass of people isn't a purpose for which I am developing AutoHotkey.
We are hardwired to learn names, so I would definitely argue that it is far easier to learn names specially if they are intuitive.
Sure. When I said "might" instead of "would", I was thinking of users whose native language is not English or anything similar. I'd guess that memorizing the property names might be more difficult for some than others, though they must memorize function names anyway.
its trivial to have the properties listed in the short description of the method/function
It may be trivial for the developer of the editor or extension to do that, less so for the user if the developer hasn't. The hint associated with the function wouldn't be displayed while you are typing the property name, as it would generally be hidden when you type ")". There may also be cases where the returned object is assigned to a variable, and the code to retrieve the property is written some time (probably a short time) after writing the function call. In any case, the parameter hints are much more effective for the actual parameters.
... even makes coding more efficient in certain conditions as you dont have to be opening the documentation, over and over for the same thing.
Again, the visual consistency of merely having both functions return an object of some kind, with varying usage and properties is not going to avoid the need to refer to the documentation over and over. Having the actual usage easier to memorize is something else altogether.

iseahound
Posts: 1434
Joined: 13 Aug 2016, 21:04
Contact:

Re: Functions returning unset by default (and divergent topics)

Post by iseahound » 24 Nov 2022, 10:19

It would have to be done in conjunction with fn(1)?, obj.method()?, as I don't see any way around it.

regarding if value? as a substitute for isset(): Nullable types (the union of unset and value) should be avoided, and and I think isset() is ugly enough to make that clear, but would support it.

OpalMonkey
Posts: 18
Joined: 23 Jan 2014, 03:02

Re: Functions returning unset by default (and divergent topics)

Post by OpalMonkey » 24 Nov 2022, 23:46

iseahound wrote:
24 Nov 2022, 10:19
It would have to be done in conjunction with fn(1)?, obj.method()?, as I don't see any way around it.

regarding if value? as a substitute for isset(): Nullable types (the union of unset and value) should be avoided, and and I think isset() is ugly enough to make that clear, but would support it.
See, this is why it's good I'm not making the decisions for this kind of thing. My main reason for liking the idea of If value? is because I find myself writing it a lot when verifying and processing parameters. Every parameter that can be left unset requires at least one check, and in a larger class, that can end up being a lot of checks.

Granted, I should really solve that with a simple hotstring, now that I think about it :lol:

lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Functions returning unset by default (and divergent topics)

Post by lexikos » 25 Nov 2022, 00:59

As I already pointed out, you can write if value ?? false.

if value? would not be possible, because a question mark at the end of the line would cause line continuation. It would have to be enclosed in parentheses.

OpalMonkey
Posts: 18
Joined: 23 Jan 2014, 03:02

Re: Functions returning unset by default (and divergent topics)

Post by OpalMonkey » 26 Nov 2022, 02:54

Ah, right. I missed that one when I was reading over the previous posts. Thanks for pointing it out again.

lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Arrays mistaken as strings?

Post by lexikos » 12 Aug 2023, 19:23

v2.1-alpha.2 implements an experimental directive, #DefaultReturn unset.

sirksel wrote:
21 Nov 2022, 22:52
1. ?. such that obj?.prop1[x]?.prop2(y1, y2)?.prop3? would return unset if anything in the chain returned unset or if any of those properties did not exist. Then one could write obj?.prop1[x]?.prop2(y1, y2)?.prop3? ?? default, without all the separate tests and HasProps. Maybe it's less of a new operator and more of an extension of the current obj? "maybe" notation.
v2.1-alpha.2 implements this as an extension of the "maybe" operator. However, some notes:

If you write obj?.prop1[x] ?? default, it will short-circuit if obj is unset but for anything else it would throw UnsetError.

Only the part immediately preceding ? can be unset. For instance, if you write .prop1[x]? or .prop2(y1, y2)?, only the return value can be unset. prop1 and prop2 cannot be unset. JavaScript supports .prop2?.(y1, y2), which would retrieve prop2 and then call it as a method only if it is not undefined. The parameters are not evaluated if the method is undefined. That implies the object must be able to report whether a method exists before it is called, which just means that it wouldn't support __Call, and mightn't support COM objects fully (if at all). For now, .prop?.() is not permitted.

An ambiguity between !HasProp and prop returning unset arises only with obj.prop?, which I think is acceptable. Just don't give the two conditions different meanings.

2. Perhaps some shortcut equality operator ?==, such that retval ?== compval is equivalent to IsSet(retval) ? retval == compval : unset and would preserve the short circuit.
I avoided setting the precedent of comparing unset to a value, partly because I've been saying it's not a value. So, like most other operators, the equality operators and switch/case do not permit unset; e.g. (a?) = b is a syntax error.

It occurred to me that the ? operator could short-circuit not only over member access, but almost anything. For instance, (a + b? * c) ?? default would short-circuit c, * and + (which are evaluated in that order). Then instead of providing a default value to compare against (e.g. (retval ?? {}) == compval always being false if retval is unset) you would provide a default value for the result of the comparison, as in (retval? == compval) ?? false, or you could put the short-circuit target (??) further outward if there are more conditions to be tested.

When ? short-circuits, it isn't permitted to be interpreted as an "omitted" parameter; there must be an additional ? if that is the intent.

I guess it could possibly even be more general... perhaps terminating a variable or expression with ? allows the unset to pass through any operator [...], causing the operator's result to be unset.
For optional chains, the . operator doesn't have a result, because the operator isn't evaluated. ? short-circuits over the operator, leaving unset as input for the next operation. In calculating the destination of the short-circuit at load-time, it is also able to determine whether the next operator can handle unset. If it can't, that's a syntax error (rather than leaving it to throw an error at runtime).

OpalMonkey wrote:
22 Nov 2022, 06:41
I keep finding myself trying to write If param? rather than If IsSet(param)
I chose not to permit this since interpretation as either if IsSet(param) or if IsSet(param) && param could be unexpected by some. x? produces the value of x if x is set, so the latter would be more correct.

Post Reply

Return to “AutoHotkey Development”